Merge tag 'regulator-fix-v4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 31 Oct 2016 17:14:09 +0000 (10:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 31 Oct 2016 17:14:09 +0000 (10:14 -0700)
Pull regulator fix from Mark Brown:
 "Fix ramp_delay warnings for v4.9

  A new warning was introduced for missing information about the time
  that regulators take to power on in v4.9. This is in theory a real
  issue but for most practical regulators the communication overhead of
  talking to the device is greater than the ramp time so a lot of
  drivers don't set it and the warning is far too noisy without
  identifying practical issues.

  Just remove the warning for now"

* tag 'regulator-fix-v4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator:
  regulator: core: silence warning: "VDD1: ramp_delay not set"

837 files changed:
CREDITS
Documentation/ABI/testing/sysfs-class-cxl
Documentation/device-mapper/dm-raid.txt
Documentation/devicetree/bindings/clock/uniphier-clock.txt
Documentation/devicetree/bindings/ipmi.txt [deleted file]
Documentation/devicetree/bindings/ipmi/aspeed,ast2400-bt-bmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ipmi/ipmi-smic.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell-orion-net.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
Documentation/devicetree/bindings/reset/uniphier-reset.txt
Documentation/devicetree/bindings/serial/cdns,uart.txt
Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
Documentation/devicetree/bindings/timer/jcore,pit.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/dwc2.txt
Documentation/filesystems/proc.txt
Documentation/gpio/board.txt
Documentation/networking/netdev-FAQ.txt
Documentation/networking/nf_conntrack-sysctl.txt
MAINTAINERS
Makefile
arch/alpha/kernel/ptrace.c
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/Makefile
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/cache.h
arch/arc/include/asm/elf.h
arch/arc/include/asm/mcip.h
arch/arc/include/asm/module.h
arch/arc/include/asm/setup.h
arch/arc/include/asm/syscalls.h
arch/arc/include/uapi/asm/unistd.h
arch/arc/kernel/mcip.c
arch/arc/kernel/module.c
arch/arc/kernel/process.c
arch/arc/kernel/setup.c
arch/arc/kernel/troubleshoot.c
arch/arc/mm/cache.c
arch/arc/mm/dma.c
arch/arc/mm/tlb.c
arch/arc/mm/tlbex.S
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/uniphier-pro5.dtsi
arch/arm/boot/dts/uniphier-pxs2.dtsi
arch/arm/boot/dts/vf500.dtsi
arch/arm/configs/multi_v7_defconfig
arch/arm/include/asm/unistd.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kvm/arm.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-uniphier/Kconfig
arch/arm/mm/abort-lv4t.S
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/Makefile
arch/arm64/boot/dts/broadcom/ns2-svk.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/exec.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/module.h
arch/arm64/include/asm/percpu.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/sysreg.h
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/head.S
arch/arm64/kernel/process.c
arch/arm64/kernel/sleep.S
arch/arm64/kernel/smp.c
arch/arm64/kernel/suspend.c
arch/arm64/kernel/traps.c
arch/arm64/mm/fault.c
arch/arm64/mm/init.c
arch/arm64/mm/numa.c
arch/blackfin/kernel/ptrace.c
arch/cris/arch-v32/drivers/cryptocop.c
arch/cris/arch-v32/kernel/ptrace.c
arch/h8300/include/asm/thread_info.h
arch/h8300/kernel/signal.c
arch/ia64/kernel/err_inject.c
arch/ia64/kernel/ptrace.c
arch/m32r/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kvm/mips.c
arch/mips/mm/gup.c
arch/powerpc/boot/main.c
arch/powerpc/include/asm/checksum.h
arch/powerpc/include/asm/cpuidle.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/tlb.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/mm/copro_fault.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/tlb-radix.c
arch/s390/include/asm/ftrace.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/unistd.h
arch/s390/kernel/dis.c
arch/s390/kernel/dumpstack.c
arch/s390/kernel/perf_event.c
arch/s390/kernel/stacktrace.c
arch/s390/kvm/intercept.c
arch/s390/mm/gup.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/init.c
arch/s390/oprofile/init.c
arch/score/kernel/ptrace.c
arch/sh/Makefile
arch/sh/boards/Kconfig
arch/sh/configs/j2_defconfig
arch/sh/mm/gup.c
arch/sparc/include/asm/cpudata_64.h
arch/sparc/include/asm/spinlock_32.h
arch/sparc/include/asm/spinlock_64.h
arch/sparc/include/asm/topology_64.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/kernel/head_64.S
arch/sparc/kernel/jump_label.c
arch/sparc/kernel/mdesc.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/lib/GENcopy_from_user.S
arch/sparc/lib/GENcopy_to_user.S
arch/sparc/lib/GENmemcpy.S
arch/sparc/lib/Makefile
arch/sparc/lib/NG2copy_from_user.S
arch/sparc/lib/NG2copy_to_user.S
arch/sparc/lib/NG2memcpy.S
arch/sparc/lib/NG4copy_from_user.S
arch/sparc/lib/NG4copy_to_user.S
arch/sparc/lib/NG4memcpy.S
arch/sparc/lib/NGcopy_from_user.S
arch/sparc/lib/NGcopy_to_user.S
arch/sparc/lib/NGmemcpy.S
arch/sparc/lib/U1copy_from_user.S
arch/sparc/lib/U1copy_to_user.S
arch/sparc/lib/U1memcpy.S
arch/sparc/lib/U3copy_from_user.S
arch/sparc/lib/U3copy_to_user.S
arch/sparc/lib/U3memcpy.S
arch/sparc/lib/copy_in_user.S
arch/sparc/lib/user_fixup.c [deleted file]
arch/sparc/mm/gup.c
arch/sparc/mm/tsb.c
arch/sparc/mm/ultra.S
arch/x86/entry/Makefile
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/entry/syscalls/syscall_64.tbl
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/intel/lbr.c
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore.c
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/io.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/rwsem.h
arch/x86/include/asm/thread_info.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/cpu/vmware.c
arch/x86/kernel/e820.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/mcount_64.S
arch/x86/kernel/quirks.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal_compat.c
arch/x86/kernel/smp.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/step.c
arch/x86/kernel/unwind_guess.c
arch/x86/kvm/ioapic.c
arch/x86/kvm/x86.c
arch/x86/mm/gup.c
arch/x86/mm/kaslr.c
arch/x86/mm/mpx.c
arch/x86/mm/pat.c
arch/x86/platform/uv/bios_uv.c
arch/x86/um/ptrace_32.c
arch/x86/um/ptrace_64.c
arch/x86/xen/enlighten.c
block/badblocks.c
block/blk-flush.c
block/blk-mq.c
drivers/Makefile
drivers/acpi/acpica/dsinit.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/evrgnini.c
drivers/acpi/acpica/nsload.c
drivers/acpi/apei/ghes.c
drivers/acpi/pci_link.c
drivers/android/binder.c
drivers/ata/ahci.c
drivers/base/Kconfig
drivers/block/DAC960.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/bluetooth/btwilink.c
drivers/bluetooth/hci_bcm.c
drivers/bus/Kconfig
drivers/char/hw_random/core.c
drivers/char/ipmi/Kconfig
drivers/char/ipmi/Makefile
drivers/char/ipmi/bt-bmc.c [new file with mode: 0644]
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/tpm/tpm-interface.c
drivers/clk/at91/clk-programmable.c
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/clk-max77686.c
drivers/clk/hisilicon/clk-hi6220.c
drivers/clk/mediatek/Kconfig
drivers/clk/mvebu/armada-37xx-periph.c
drivers/clk/samsung/clk-exynos-audss.c
drivers/clk/uniphier/clk-uniphier-core.c
drivers/clk/uniphier/clk-uniphier-mio.c
drivers/clk/uniphier/clk-uniphier-mux.c
drivers/clk/uniphier/clk-uniphier.h
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/jcore-pit.c [new file with mode: 0644]
drivers/clocksource/timer-sun5i.c
drivers/cpufreq/intel_pstate.c
drivers/dax/Kconfig
drivers/dax/pmem.c
drivers/extcon/extcon-qcom-spmi-misc.c
drivers/firewire/nosy.c
drivers/firmware/efi/libstub/Makefile
drivers/gpio/Kconfig
drivers/gpio/gpio-ath79.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-stmpe.c
drivers/gpio/gpio-ts4800.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/cz_dpm.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_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/tonga_ih.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/etnaviv/etnaviv_buffer.c
drivers/gpu/drm/etnaviv/etnaviv_gem.c
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_i2c.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/via/via_dmablit.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/hid/hid-dr.c
drivers/hid/hid-ids.h
drivers/hid/hid-led.c
drivers/hid/usbhid/hid-quirks.c
drivers/hv/hv_util.c
drivers/hwmon/adm9240.c
drivers/hwmon/max31790.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-digicolor.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-jz4780.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/busses/i2c-xlr.c
drivers/i2c/i2c-core.c
drivers/iio/adc/Kconfig
drivers/iio/chemical/atlas-ph-sensor.c
drivers/iio/temperature/maxim_thermocouple.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/qedr/Kconfig
drivers/infiniband/hw/qib/qib_user_pages.c
drivers/infiniband/hw/usnic/usnic_uiom.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/ipack/ipack.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-eznps.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-jcore-aic.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-rq.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/media/pci/ivtv/ivtv-udma.c
drivers/media/pci/ivtv/ivtv-yuv.c
drivers/media/platform/omap/omap_vout.c
drivers/media/v4l2-core/videobuf-dma-sg.c
drivers/media/v4l2-core/videobuf2-memops.c
drivers/memstick/host/rtsx_usb_ms.c
drivers/misc/cxl/api.c
drivers/misc/cxl/context.c
drivers/misc/cxl/cxl.h
drivers/misc/cxl/file.c
drivers/misc/cxl/guest.c
drivers/misc/cxl/main.c
drivers/misc/cxl/pci.c
drivers/misc/cxl/sysfs.c
drivers/misc/genwqe/card_utils.c
drivers/misc/mei/hw-txe.c
drivers/misc/mic/scif/scif_rma.c
drivers/misc/sgi-gru/grufault.c
drivers/misc/sgi-gru/grumain.c
drivers/misc/vmw_vmci/vmci_doorbell.c
drivers/misc/vmw_vmci/vmci_driver.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.h
drivers/mmc/core/mmc.c
drivers/mmc/host/rtsx_usb_sdmmc.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-pci.h
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/fastmap.c
drivers/net/dsa/b53/b53_mmap.c
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/aurora/nb8800.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
drivers/net/ethernet/chelsio/cxgb4/sched.c
drivers/net/ethernet/cisco/enic/vnic_rq.c
drivers/net/ethernet/ezchip/nps_enet.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns_mdio.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_clock.c
drivers/net/ethernet/mellanox/mlx4/en_cq.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_port.c
drivers/net/ethernet/mellanox/mlx4/en_selftest.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/alloc.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/qlogic/Kconfig
drivers/net/ethernet/qlogic/qed/Makefile
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_dcbx.c
drivers/net/ethernet/qlogic/qed/qed_debug.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_ll2.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_roce.c
drivers/net/ethernet/qlogic/qed/qed_roce.h
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/qlogic/qede/Makefile
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_ethtool.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/synopsys/dwc_eth_qos.c
drivers/net/geneve.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macsec.c
drivers/net/phy/at803x.c
drivers/net/phy/dp83848.c
drivers/net/usb/asix_common.c
drivers/net/usb/kalmia.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wan/Kconfig
drivers/net/wan/slic_ds26522.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
drivers/net/wireless/realtek/rtlwifi/core.c
drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
drivers/net/wireless/realtek/rtlwifi/wifi.h
drivers/net/wireless/ti/wlcore/sdio.c
drivers/nvdimm/Kconfig
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/pmem.c
drivers/nvme/host/core.c
drivers/nvme/host/pci.c
drivers/nvme/host/scsi.c
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/core.c
drivers/nvme/target/discovery.c
drivers/pci/host/pci-layerscape.c
drivers/pci/host/pcie-designware-plat.c
drivers/pci/msi.c
drivers/perf/xgene_pmu.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/platform/goldfish/goldfish_pipe.c
drivers/platform/x86/Kconfig
drivers/platform/x86/ideapad-laptop.c
drivers/rapidio/devices/rio_mport_cdev.c
drivers/reset/reset-uniphier.c
drivers/s390/block/dasd_eckd.c
drivers/s390/cio/chp.c
drivers/s390/scsi/zfcp_dbf.c
drivers/scsi/NCR5380.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/ipr.c
drivers/scsi/libiscsi.c
drivers/scsi/scsi_dh.c
drivers/scsi/scsi_scan.c
drivers/scsi/st.c
drivers/staging/android/ion/ion.c
drivers/staging/android/ion/ion_of.c
drivers/staging/greybus/arche-platform.c
drivers/staging/greybus/es2.c
drivers/staging/greybus/gpio.c
drivers/staging/greybus/module.c
drivers/staging/greybus/uart.c
drivers/staging/iio/accel/sca3000_core.c
drivers/staging/lustre/lustre/llite/lproc_llite.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/staging/wilc1000/host_interface.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/target/target_core_xcopy.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_sess.c
drivers/thermal/intel_pch_thermal.c
drivers/thermal/intel_powerclamp.c
drivers/tty/serial/8250/8250_lpss.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/8250/8250_uniphier.c
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/sc16is7xx.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/stm32-usart.h
drivers/tty/serial/xilinx_uartps.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/host.c
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/omap2430.c
drivers/usb/renesas_usbhs/rcar3.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/usb-serial.c
drivers/usb/wusbcore/crypto.c
drivers/video/fbdev/pvr2fb.c
drivers/virt/fsl_hypervisor.c
drivers/vme/vme.c
drivers/watchdog/wdat_wdt.c
drivers/xen/manage.c
drivers/xen/xenbus/xenbus_dev_frontend.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/afs/cmservice.c
fs/afs/fsclient.c
fs/afs/internal.h
fs/afs/rxrpc.c
fs/btrfs/compression.c
fs/btrfs/send.c
fs/btrfs/tree-log.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/super.c
fs/ceph/xattr.c
fs/crypto/crypto.c
fs/crypto/policy.c
fs/exec.c
fs/exofs/dir.c
fs/ext2/inode.c
fs/ext4/block_validity.c
fs/ext4/mballoc.h
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/sysfs.c
fs/ext4/xattr.c
fs/f2fs/gc.c
fs/iomap.c
fs/isofs/inode.c
fs/jbd2/transaction.c
fs/kernfs/file.c
fs/locks.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/nfs4proc.c
fs/orangefs/dcache.c
fs/orangefs/file.c
fs/orangefs/namei.c
fs/orangefs/orangefs-kernel.h
fs/proc/array.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/ubifs/dir.c
fs/ubifs/xattr.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_dquot_buf.c
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/libxfs/xfs_inode_buf.h
fs/xfs/xfs_file.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_reflink.c
fs/xfs/xfs_reflink.h
fs/xfs/xfs_sysfs.c
fs/xfs/xfs_trace.h
include/acpi/pcc.h
include/asm-generic/export.h
include/linux/acpi.h
include/linux/clk-provider.h
include/linux/cpufreq.h
include/linux/cpuhotplug.h
include/linux/hyperv.h
include/linux/io.h
include/linux/iomap.h
include/linux/ipv6.h
include/linux/irqchip/arm-gic-v3.h
include/linux/kasan.h
include/linux/kconfig.h
include/linux/mlx4/device.h
include/linux/mlx5/driver.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/netdevice.h
include/linux/nvme.h
include/linux/perf_event.h
include/linux/qed/qed_if.h
include/linux/qed/qede_roce.h
include/linux/regmap.h
include/linux/skbuff.h
include/linux/syscalls.h
include/linux/thread_info.h
include/net/addrconf.h
include/net/cfg80211.h
include/net/if_inet6.h
include/net/ip.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/mac80211.h
include/net/sock.h
include/net/tcp.h
include/net/udp.h
include/net/vxlan.h
include/target/target_core_base.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/Kbuild
include/uapi/linux/bt-bmc.h [new file with mode: 0644]
include/uapi/linux/ethtool.h
include/uapi/linux/rtnetlink.h
ipc/msgutil.c
kernel/cpu.c
kernel/events/core.c
kernel/events/uprobes.c
kernel/irq/manage.c
kernel/kcov.c
kernel/power/suspend.c
kernel/printk/printk.c
kernel/ptrace.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/wait.c
kernel/softirq.c
kernel/time/alarmtimer.c
kernel/time/timer.c
lib/Kconfig.debug
lib/genalloc.c
lib/stackdepot.c
lib/test_bpf.c
mm/Kconfig
mm/filemap.c
mm/frame_vector.c
mm/gup.c
mm/kasan/kasan.c
mm/kmemleak.c
mm/list_lru.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mprotect.c
mm/nommu.c
mm/page_alloc.c
mm/process_vm_access.c
mm/slab.c
mm/slab.h
mm/util.c
mm/vmscan.c
net/8021q/vlan.c
net/batman-adv/hard-interface.c
net/batman-adv/log.h
net/batman-adv/originator.c
net/bluetooth/hci_request.c
net/bluetooth/hci_request.h
net/bluetooth/mgmt.c
net/bridge/br_multicast.c
net/ceph/pagevec.c
net/core/dev.c
net/core/flow_dissector.c
net/core/net_namespace.c
net/core/pktgen.c
net/core/sock_reuseport.c
net/ethernet/eth.c
net/hsr/hsr_forward.c
net/ipv4/af_inet.c
net/ipv4/fou.c
net/ipv4/gre_offload.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/udp.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/mac80211/aes_ccm.c
net/mac80211/aes_ccm.h
net/mac80211/aes_gcm.c
net/mac80211/aes_gcm.h
net/mac80211/aes_gmac.c
net/mac80211/aes_gmac.h
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/wpa.c
net/ncsi/internal.h
net/ncsi/ncsi-aen.c
net/ncsi/ncsi-manage.c
net/netfilter/core.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_internals.h
net/netfilter/nf_queue.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_dynset.c
net/netfilter/nft_exthdr.c
net/netfilter/nft_hash.c
net/netfilter/nft_range.c
net/netfilter/x_tables.c
net/netfilter/xt_NFLOG.c
net/netfilter/xt_hashlimit.c
net/netfilter/xt_ipcomp.c
net/packet/af_packet.c
net/rds/Makefile
net/rds/rds.h
net/rxrpc/call_object.c
net/rxrpc/peer_object.c
net/sched/act_api.c
net/sched/act_mirred.c
net/sched/cls_api.c
net/sctp/output.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/switchdev/switchdev.c
net/tipc/bcast.c
net/tipc/bcast.h
net/tipc/link.c
net/tipc/msg.h
net/tipc/name_distr.c
net/tipc/node.c
net/wireless/sysfs.c
net/wireless/util.c
samples/bpf/parse_ldabs.c
samples/bpf/parse_simple.c
samples/bpf/parse_varlen.c
samples/bpf/tcbpf1_kern.c
samples/bpf/tcbpf2_kern.c
samples/bpf/test_cgrp2_tc_kern.c
security/keys/Kconfig
security/keys/big_key.c
security/keys/proc.c
security/selinux/hooks.c
security/tomoyo/domain.c
sound/core/seq/seq_timer.c
sound/pci/asihpi/hpioctl.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/usb/quirks-table.h
tools/arch/x86/include/asm/cpufeatures.h
tools/objtool/arch/x86/decode.c
tools/objtool/builtin-check.c
tools/perf/jvmti/Makefile
tools/perf/ui/browsers/hists.c
tools/perf/util/header.c
tools/perf/util/parse-events.l
virt/kvm/async_pf.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 513aaa3..8373676 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1864,10 +1864,11 @@ S: The Netherlands
 
 N: Martin Kepplinger
 E: martink@posteo.de
-E: martin.kepplinger@theobroma-systems.com
+E: martin.kepplinger@ginzinger.com
 W: http://www.martinkepplinger.com
 D: mma8452 accelerators iio driver
-D: Kernel cleanups
+D: pegasus_notetaker input driver
+D: Kernel fixes and cleanups
 S: Garnisonstraße 26
 S: 4020 Linz
 S: Austria
index 4ba0a2a..640f65e 100644 (file)
@@ -220,8 +220,11 @@ What:           /sys/class/cxl/<card>/reset
 Date:           October 2014
 Contact:        linuxppc-dev@lists.ozlabs.org
 Description:    write only
-                Writing 1 will issue a PERST to card which may cause the card
-                to reload the FPGA depending on load_image_on_perst.
+                Writing 1 will issue a PERST to card provided there are no
+                contexts active on any one of the card AFUs. This may cause
+                the card to reload the FPGA depending on load_image_on_perst.
+                Writing -1 will do a force PERST irrespective of any active
+                contexts on the card AFUs.
 Users:         https://github.com/ibm-capi/libcxl
 
 What:          /sys/class/cxl/<card>/perst_reloads_same_image (not in a guest)
index e5b6497..c75b64a 100644 (file)
@@ -309,3 +309,4 @@ Version History
        with a reshape in progress.
 1.9.0   Add support for RAID level takeover/reshape/region size
        and set size reduction.
+1.9.1   Fix activation of existing RAID 4/10 mapped devices
index c7179d3..8121630 100644 (file)
@@ -24,7 +24,7 @@ Example:
                reg = <0x61840000 0x4000>;
 
                clock {
-                       compatible = "socionext,uniphier-ld20-clock";
+                       compatible = "socionext,uniphier-ld11-clock";
                        #clock-cells = <1>;
                };
 
@@ -43,8 +43,8 @@ Provided clocks:
 21: USB3 ch1 PHY1
 
 
-Media I/O (MIO) clock
----------------------
+Media I/O (MIO) clock, SD clock
+-------------------------------
 
 Required properties:
 - compatible: should be one of the following:
@@ -52,10 +52,10 @@ Required properties:
     "socionext,uniphier-ld4-mio-clock"  - for LD4 SoC.
     "socionext,uniphier-pro4-mio-clock" - for Pro4 SoC.
     "socionext,uniphier-sld8-mio-clock" - for sLD8 SoC.
-    "socionext,uniphier-pro5-mio-clock" - for Pro5 SoC.
-    "socionext,uniphier-pxs2-mio-clock" - for PXs2/LD6b SoC.
+    "socionext,uniphier-pro5-sd-clock"  - for Pro5 SoC.
+    "socionext,uniphier-pxs2-sd-clock"  - for PXs2/LD6b SoC.
     "socionext,uniphier-ld11-mio-clock" - for LD11 SoC.
-    "socionext,uniphier-ld20-mio-clock" - for LD20 SoC.
+    "socionext,uniphier-ld20-sd-clock"  - for LD20 SoC.
 - #clock-cells: should be 1.
 
 Example:
@@ -66,7 +66,7 @@ Example:
                reg = <0x59810000 0x800>;
 
                clock {
-                       compatible = "socionext,uniphier-ld20-mio-clock";
+                       compatible = "socionext,uniphier-ld11-mio-clock";
                        #clock-cells = <1>;
                };
 
@@ -112,7 +112,7 @@ Example:
                reg = <0x59820000 0x200>;
 
                clock {
-                       compatible = "socionext,uniphier-ld20-peri-clock";
+                       compatible = "socionext,uniphier-ld11-peri-clock";
                        #clock-cells = <1>;
                };
 
diff --git a/Documentation/devicetree/bindings/ipmi.txt b/Documentation/devicetree/bindings/ipmi.txt
deleted file mode 100644 (file)
index d5f1a87..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-IPMI device
-
-Required properties:
-- compatible: should be one of ipmi-kcs, ipmi-smic, or ipmi-bt
-- device_type: should be ipmi
-- reg: Address and length of the register set for the device
-
-Optional properties:
-- interrupts: The interrupt for the device.  Without this the interface
-       is polled.
-- reg-size - The size of the register.  Defaults to 1
-- reg-spacing - The number of bytes between register starts.  Defaults to 1
-- reg-shift - The amount to shift the registers to the right to get the data
-       into bit zero.
-
-Example:
-
-smic@fff3a000 {
-       compatible = "ipmi-smic";
-       device_type = "ipmi";
-       reg = <0xfff3a000 0x1000>;
-       interrupts = <0 24 4>;
-       reg-size = <4>;
-       reg-spacing = <4>;
-};
diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-bt-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-bt-bmc.txt
new file mode 100644 (file)
index 0000000..fbbacd9
--- /dev/null
@@ -0,0 +1,23 @@
+* Aspeed BT (Block Transfer) IPMI interface
+
+The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs
+(BaseBoard Management Controllers) and the BT interface can be used to
+perform in-band IPMI communication with their host.
+
+Required properties:
+
+- compatible : should be "aspeed,ast2400-bt-bmc"
+- reg: physical address and size of the registers
+
+Optional properties:
+
+- interrupts: interrupt generated by the BT interface. without an
+  interrupt, the driver will operate in poll mode.
+
+Example:
+
+       ibt@1e789140 {
+               compatible = "aspeed,ast2400-bt-bmc";
+               reg = <0x1e789140 0x18>;
+               interrupts = <8>;
+       };
diff --git a/Documentation/devicetree/bindings/ipmi/ipmi-smic.txt b/Documentation/devicetree/bindings/ipmi/ipmi-smic.txt
new file mode 100644 (file)
index 0000000..d5f1a87
--- /dev/null
@@ -0,0 +1,25 @@
+IPMI device
+
+Required properties:
+- compatible: should be one of ipmi-kcs, ipmi-smic, or ipmi-bt
+- device_type: should be ipmi
+- reg: Address and length of the register set for the device
+
+Optional properties:
+- interrupts: The interrupt for the device.  Without this the interface
+       is polled.
+- reg-size - The size of the register.  Defaults to 1
+- reg-spacing - The number of bytes between register starts.  Defaults to 1
+- reg-shift - The amount to shift the registers to the right to get the data
+       into bit zero.
+
+Example:
+
+smic@fff3a000 {
+       compatible = "ipmi-smic";
+       device_type = "ipmi";
+       reg = <0xfff3a000 0x1000>;
+       interrupts = <0 24 4>;
+       reg-size = <4>;
+       reg-spacing = <4>;
+};
index bce52b2..6fd988c 100644 (file)
@@ -49,6 +49,7 @@ Optional port properties:
 and
 
  - phy-handle: See ethernet.txt file in the same directory.
+ - phy-mode: See ethernet.txt file in the same directory.
 
 or
 
index 5e60ad1..2ad18c4 100644 (file)
@@ -43,7 +43,9 @@ aspeed,ast2500-pinctrl, aspeed,g5-pinctrl:
 
 GPID0 GPID2 GPIE0 I2C10 I2C11 I2C12 I2C13 I2C14 I2C3 I2C4 I2C5 I2C6 I2C7 I2C8
 I2C9 MAC1LINK MDIO1 MDIO2 OSCCLK PEWAKE PWM0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7
-RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 TIMER4 TIMER5 TIMER6 TIMER7 TIMER8
+RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
+TIMER7 TIMER8 VGABIOSROM
+
 
 Examples:
 
index e6bbfcc..5020524 100644 (file)
@@ -6,25 +6,25 @@ System reset
 
 Required properties:
 - compatible: should be one of the following:
-    "socionext,uniphier-sld3-reset" - for PH1-sLD3 SoC.
-    "socionext,uniphier-ld4-reset"  - for PH1-LD4 SoC.
-    "socionext,uniphier-pro4-reset" - for PH1-Pro4 SoC.
-    "socionext,uniphier-sld8-reset" - for PH1-sLD8 SoC.
-    "socionext,uniphier-pro5-reset" - for PH1-Pro5 SoC.
-    "socionext,uniphier-pxs2-reset" - for ProXstream2/PH1-LD6b SoC.
-    "socionext,uniphier-ld11-reset" - for PH1-LD11 SoC.
-    "socionext,uniphier-ld20-reset" - for PH1-LD20 SoC.
+    "socionext,uniphier-sld3-reset" - for sLD3 SoC.
+    "socionext,uniphier-ld4-reset"  - for LD4 SoC.
+    "socionext,uniphier-pro4-reset" - for Pro4 SoC.
+    "socionext,uniphier-sld8-reset" - for sLD8 SoC.
+    "socionext,uniphier-pro5-reset" - for Pro5 SoC.
+    "socionext,uniphier-pxs2-reset" - for PXs2/LD6b SoC.
+    "socionext,uniphier-ld11-reset" - for LD11 SoC.
+    "socionext,uniphier-ld20-reset" - for LD20 SoC.
 - #reset-cells: should be 1.
 
 Example:
 
        sysctrl@61840000 {
-               compatible = "socionext,uniphier-ld20-sysctrl",
+               compatible = "socionext,uniphier-ld11-sysctrl",
                             "simple-mfd", "syscon";
                reg = <0x61840000 0x4000>;
 
                reset {
-                       compatible = "socionext,uniphier-ld20-reset";
+                       compatible = "socionext,uniphier-ld11-reset";
                        #reset-cells = <1>;
                };
 
@@ -32,30 +32,30 @@ Example:
        };
 
 
-Media I/O (MIO) reset
----------------------
+Media I/O (MIO) reset, SD reset
+-------------------------------
 
 Required properties:
 - compatible: should be one of the following:
-    "socionext,uniphier-sld3-mio-reset" - for PH1-sLD3 SoC.
-    "socionext,uniphier-ld4-mio-reset"  - for PH1-LD4 SoC.
-    "socionext,uniphier-pro4-mio-reset" - for PH1-Pro4 SoC.
-    "socionext,uniphier-sld8-mio-reset" - for PH1-sLD8 SoC.
-    "socionext,uniphier-pro5-mio-reset" - for PH1-Pro5 SoC.
-    "socionext,uniphier-pxs2-mio-reset" - for ProXstream2/PH1-LD6b SoC.
-    "socionext,uniphier-ld11-mio-reset" - for PH1-LD11 SoC.
-    "socionext,uniphier-ld20-mio-reset" - for PH1-LD20 SoC.
+    "socionext,uniphier-sld3-mio-reset" - for sLD3 SoC.
+    "socionext,uniphier-ld4-mio-reset"  - for LD4 SoC.
+    "socionext,uniphier-pro4-mio-reset" - for Pro4 SoC.
+    "socionext,uniphier-sld8-mio-reset" - for sLD8 SoC.
+    "socionext,uniphier-pro5-sd-reset"  - for Pro5 SoC.
+    "socionext,uniphier-pxs2-sd-reset"  - for PXs2/LD6b SoC.
+    "socionext,uniphier-ld11-mio-reset" - for LD11 SoC.
+    "socionext,uniphier-ld20-sd-reset"  - for LD20 SoC.
 - #reset-cells: should be 1.
 
 Example:
 
        mioctrl@59810000 {
-               compatible = "socionext,uniphier-ld20-mioctrl",
+               compatible = "socionext,uniphier-ld11-mioctrl",
                             "simple-mfd", "syscon";
                reg = <0x59810000 0x800>;
 
                reset {
-                       compatible = "socionext,uniphier-ld20-mio-reset";
+                       compatible = "socionext,uniphier-ld11-mio-reset";
                        #reset-cells = <1>;
                };
 
@@ -68,24 +68,24 @@ Peripheral reset
 
 Required properties:
 - compatible: should be one of the following:
-    "socionext,uniphier-ld4-peri-reset"  - for PH1-LD4 SoC.
-    "socionext,uniphier-pro4-peri-reset" - for PH1-Pro4 SoC.
-    "socionext,uniphier-sld8-peri-reset" - for PH1-sLD8 SoC.
-    "socionext,uniphier-pro5-peri-reset" - for PH1-Pro5 SoC.
-    "socionext,uniphier-pxs2-peri-reset" - for ProXstream2/PH1-LD6b SoC.
-    "socionext,uniphier-ld11-peri-reset" - for PH1-LD11 SoC.
-    "socionext,uniphier-ld20-peri-reset" - for PH1-LD20 SoC.
+    "socionext,uniphier-ld4-peri-reset"  - for LD4 SoC.
+    "socionext,uniphier-pro4-peri-reset" - for Pro4 SoC.
+    "socionext,uniphier-sld8-peri-reset" - for sLD8 SoC.
+    "socionext,uniphier-pro5-peri-reset" - for Pro5 SoC.
+    "socionext,uniphier-pxs2-peri-reset" - for PXs2/LD6b SoC.
+    "socionext,uniphier-ld11-peri-reset" - for LD11 SoC.
+    "socionext,uniphier-ld20-peri-reset" - for LD20 SoC.
 - #reset-cells: should be 1.
 
 Example:
 
        perictrl@59820000 {
-               compatible = "socionext,uniphier-ld20-perictrl",
+               compatible = "socionext,uniphier-ld11-perictrl",
                             "simple-mfd", "syscon";
                reg = <0x59820000 0x200>;
 
                reset {
-                       compatible = "socionext,uniphier-ld20-peri-reset";
+                       compatible = "socionext,uniphier-ld11-peri-reset";
                        #reset-cells = <1>;
                };
 
index a3eb154..227bb77 100644 (file)
@@ -1,7 +1,9 @@
 Binding for Cadence UART Controller
 
 Required properties:
-- compatible : should be "cdns,uart-r1p8", or "xlnx,xuartps"
+- compatible :
+  Use "xlnx,xuartps","cdns,uart-r1p8" for Zynq-7xxx SoC.
+  Use "xlnx,zynqmp-uart","cdns,uart-r1p12" for Zynq Ultrascale+ MPSoC.
 - reg: Should contain UART controller registers location and length.
 - interrupts: Should contain UART controller interrupts.
 - clocks: Must contain phandles to the UART clocks
index 1e4000d..8d27d1a 100644 (file)
@@ -9,6 +9,14 @@ Required properties:
     - "renesas,scifb-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFB compatible UART.
     - "renesas,scifa-r8a7740" for R8A7740 (R-Mobile A1) SCIFA compatible UART.
     - "renesas,scifb-r8a7740" for R8A7740 (R-Mobile A1) SCIFB compatible UART.
+    - "renesas,scif-r8a7743" for R8A7743 (RZ/G1M) SCIF compatible UART.
+    - "renesas,scifa-r8a7743" for R8A7743 (RZ/G1M) SCIFA compatible UART.
+    - "renesas,scifb-r8a7743" for R8A7743 (RZ/G1M) SCIFB compatible UART.
+    - "renesas,hscif-r8a7743" for R8A7743 (RZ/G1M) HSCIF compatible UART.
+    - "renesas,scif-r8a7745" for R8A7745 (RZ/G1E) SCIF compatible UART.
+    - "renesas,scifa-r8a7745" for R8A7745 (RZ/G1E) SCIFA compatible UART.
+    - "renesas,scifb-r8a7745" for R8A7745 (RZ/G1E) SCIFB compatible UART.
+    - "renesas,hscif-r8a7745" for R8A7745 (RZ/G1E) HSCIF compatible UART.
     - "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
     - "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
     - "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.
diff --git a/Documentation/devicetree/bindings/timer/jcore,pit.txt b/Documentation/devicetree/bindings/timer/jcore,pit.txt
new file mode 100644 (file)
index 0000000..af5dd35
--- /dev/null
@@ -0,0 +1,24 @@
+J-Core Programmable Interval Timer and Clocksource
+
+Required properties:
+
+- compatible: Must be "jcore,pit".
+
+- reg: Memory region(s) for timer/clocksource registers. For SMP,
+  there should be one region per cpu, indexed by the sequential,
+  zero-based hardware cpu number.
+
+- interrupts: An interrupt to assign for the timer. The actual pit
+  core is integrated with the aic and allows the timer interrupt
+  assignment to be programmed by software, but this property is
+  required in order to reserve an interrupt number that doesn't
+  conflict with other devices.
+
+
+Example:
+
+timer@200 {
+       compatible = "jcore,pit";
+       reg = < 0x200 0x30 0x500 0x30 >;
+       interrupts = < 0x48 >;
+};
index 455f2c3..2c30a54 100644 (file)
@@ -28,10 +28,7 @@ Refer to phy/phy-bindings.txt for generic phy consumer properties
 - g-use-dma: enable dma usage in gadget driver.
 - g-rx-fifo-size: size of rx fifo size in gadget mode.
 - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
-
-Deprecated properties:
-- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0)
-  in gadget mode.
+- g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
 
 Example:
 
index 219ffd4..74329fd 100644 (file)
@@ -395,32 +395,6 @@ is not associated with a file:
 
  or if empty, the mapping is anonymous.
 
-The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
-of the individual tasks of a process. In this file you will see a mapping marked
-as [stack] if that task sees it as a stack. Hence, for the example above, the
-task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
-
-08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
-08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
-0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
-a7cb1000-a7cb2000 ---p 00000000 00:00 0
-a7cb2000-a7eb2000 rw-p 00000000 00:00 0
-a7eb2000-a7eb3000 ---p 00000000 00:00 0
-a7eb3000-a7ed5000 rw-p 00000000 00:00 0          [stack]
-a7ed5000-a8008000 r-xp 00000000 03:00 4222       /lib/libc.so.6
-a8008000-a800a000 r--p 00133000 03:00 4222       /lib/libc.so.6
-a800a000-a800b000 rw-p 00135000 03:00 4222       /lib/libc.so.6
-a800b000-a800e000 rw-p 00000000 00:00 0
-a800e000-a8022000 r-xp 00000000 03:00 14462      /lib/libpthread.so.0
-a8022000-a8023000 r--p 00013000 03:00 14462      /lib/libpthread.so.0
-a8023000-a8024000 rw-p 00014000 03:00 14462      /lib/libpthread.so.0
-a8024000-a8027000 rw-p 00000000 00:00 0
-a8027000-a8043000 r-xp 00000000 03:00 8317       /lib/ld-linux.so.2
-a8043000-a8044000 r--p 0001b000 03:00 8317       /lib/ld-linux.so.2
-a8044000-a8045000 rw-p 0001c000 03:00 8317       /lib/ld-linux.so.2
-aff35000-aff4a000 rw-p 00000000 00:00 0
-ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
-
 The /proc/PID/smaps is an extension based on maps, showing the memory
 consumption for each of the process's mappings. For each of mappings there
 is a series of lines such as the following:
index 40884c4..a0f6189 100644 (file)
@@ -6,7 +6,7 @@ Note that it only applies to the new descriptor-based interface. For a
 description of the deprecated integer-based GPIO interface please refer to
 gpio-legacy.txt (actually, there is no real mapping possible with the old
 interface; you just fetch an integer from somewhere and request the
-corresponding GPIO.
+corresponding GPIO).
 
 All platforms can enable the GPIO library, but if the platform strictly
 requires GPIO functionality to be present, it needs to select GPIOLIB from its
@@ -162,6 +162,9 @@ The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
 
 Since the "led" GPIOs are mapped as active-high, this example will switch their
 signals to 1, i.e. enabling the LEDs. And for the "power" GPIO, which is mapped
-as active-low, its actual signal will be 0 after this code. Contrary to the legacy
-integer GPIO interface, the active-low property is handled during mapping and is
-thus transparent to GPIO consumers.
+as active-low, its actual signal will be 0 after this code. Contrary to the
+legacy integer GPIO interface, the active-low property is handled during
+mapping and is thus transparent to GPIO consumers.
+
+A set of functions such as gpiod_set_value() is available to work with
+the new descriptor-oriented interface.
index 0fe1c6e..a20b2fa 100644 (file)
@@ -29,8 +29,8 @@ A: There are always two trees (git repositories) in play.  Both are driven
    Linus, and net-next is where the new code goes for the future release.
    You can find the trees here:
 
-       http://git.kernel.org/?p=linux/kernel/git/davem/net.git
-       http://git.kernel.org/?p=linux/kernel/git/davem/net-next.git
+        https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+        https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 
 Q: How often do changes from these trees make it to the mainline Linus tree?
 
@@ -76,7 +76,7 @@ Q: So where are we now in this cycle?
 
 A: Load the mainline (Linus) page here:
 
-       http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git
+       https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 
    and note the top of the "tags" section.  If it is rc1, it is early
    in the dev cycle.  If it was tagged rc7 a week ago, then a release
@@ -123,7 +123,7 @@ A: Normally Greg Kroah-Hartman collects stable commits himself, but
 
    It contains the patches which Dave has selected, but not yet handed
    off to Greg.  If Greg already has the patch, then it will be here:
-       http://git.kernel.org/cgit/linux/kernel/git/stable/stable-queue.git
+       https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git
 
    A quick way to find whether the patch is in this stable-queue is
    to simply clone the repo, and then git grep the mainline commit ID, e.g.
index 4fb51d3..399e4e8 100644 (file)
@@ -33,24 +33,6 @@ nf_conntrack_events - BOOLEAN
        If this option is enabled, the connection tracking code will
        provide userspace with connection tracking events via ctnetlink.
 
-nf_conntrack_events_retry_timeout - INTEGER (seconds)
-       default 15
-
-       This option is only relevant when "reliable connection tracking
-       events" are used.  Normally, ctnetlink is "lossy", that is,
-       events are normally dropped when userspace listeners can't keep up.
-
-       Userspace can request "reliable event mode".  When this mode is
-       active, the conntrack will only be destroyed after the event was
-       delivered.  If event delivery fails, the kernel periodically
-       re-tries to send the event to userspace.
-
-       This is the maximum interval the kernel should use when re-trying
-       to deliver the destroy event.
-
-       A higher number means there will be fewer delivery retries and it
-       will take longer for a backlog to be processed.
-
 nf_conntrack_expect_max - INTEGER
        Maximum size of expectation table.  Default value is
        nf_conntrack_buckets / 256. Minimum is 1.
index 1cd38a7..4012c2f 100644 (file)
@@ -1442,6 +1442,7 @@ F:        drivers/cpufreq/mvebu-cpufreq.c
 F:     arch/arm/configs/mvebu_*_defconfig
 
 ARM/Marvell Berlin SoC support
+M:     Jisheng Zhang <jszhang@marvell.com>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -2551,15 +2552,18 @@ S:      Supported
 F:     drivers/net/ethernet/broadcom/genet/
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-M:     Sony Chacko <sony.chacko@qlogic.com>
-M:     Dept-HSGLinuxNICDev@qlogic.com
+M:     Rasesh Mody <rasesh.mody@cavium.com>
+M:     Harish Patil <harish.patil@cavium.com>
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2.*
 F:     drivers/net/ethernet/broadcom/bnx2_*
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <ariel.elior@qlogic.com>
+M:     Yuval Mintz <Yuval.Mintz@cavium.com>
+M:     Ariel Elior <ariel.elior@cavium.com>
+M:     everest-linux-l2@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
@@ -2766,7 +2770,9 @@ S:        Supported
 F:     drivers/scsi/bfa/
 
 BROCADE BNA 10 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@qlogic.com>
+M:     Rasesh Mody <rasesh.mody@cavium.com>
+M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/brocade/bna/
@@ -4620,8 +4626,9 @@ F:        sound/usb/misc/ua101.c
 
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Matt Fleming <matt@codeblueprint.co.uk>
+M:     Ard Biesheuvel <ard.biesheuvel@linaro.org>
 L:     linux-efi@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git
 S:     Maintained
 F:     Documentation/efi-stub.txt
 F:     arch/ia64/kernel/efi.c
@@ -5286,6 +5293,12 @@ M:       Joe Perches <joe@perches.com>
 S:     Maintained
 F:     scripts/get_maintainer.pl
 
+GENWQE (IBM Generic Workqueue Card)
+M:     Frank Haverkamp <haver@linux.vnet.ibm.com>
+M:     Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
+S:     Supported
+F:     drivers/misc/genwqe/
+
 GFS2 FILE SYSTEM
 M:     Steven Whitehouse <swhiteho@redhat.com>
 M:     Bob Peterson <rpeterso@redhat.com>
@@ -8099,6 +8112,7 @@ S:        Maintained
 F:     drivers/media/dvb-frontends/mn88473*
 
 MODULE SUPPORT
+M:     Jessica Yu <jeyu@redhat.com>
 M:     Rusty Russell <rusty@rustcorp.com.au>
 S:     Maintained
 F:     include/linux/module.h
@@ -8212,7 +8226,7 @@ F:        include/linux/mfd/
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
 M:     Ulf Hansson <ulf.hansson@linaro.org>
 L:     linux-mmc@vger.kernel.org
-T:     git git://git.linaro.org/people/ulf.hansson/mmc.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
 S:     Maintained
 F:     Documentation/devicetree/bindings/mmc/
 F:     drivers/mmc/
@@ -8508,11 +8522,10 @@ F:      Documentation/devicetree/bindings/net/wireless/
 F:     drivers/net/wireless/
 
 NETXEN (1/10) GbE SUPPORT
-M:     Manish Chopra <manish.chopra@qlogic.com>
-M:     Sony Chacko <sony.chacko@qlogic.com>
-M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
+M:     Manish Chopra <manish.chopra@cavium.com>
+M:     Rahul Verma <rahul.verma@cavium.com>
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
-W:     http://www.qlogic.com
 S:     Supported
 F:     drivers/net/ethernet/qlogic/netxen/
 
@@ -9299,7 +9312,7 @@ S:        Maintained
 F:     drivers/pci/host/*designware*
 
 PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
-M:     Joao Pinto <jpinto@synopsys.com>
+M:     Jose Abreu <Jose.Abreu@synopsys.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/designware-pcie.txt
@@ -9888,33 +9901,32 @@ F:      Documentation/scsi/LICENSE.qla4xxx
 F:     drivers/scsi/qla4xxx/
 
 QLOGIC QLA3XXX NETWORK DRIVER
-M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
-M:     Ron Mercer <ron.mercer@qlogic.com>
-M:     linux-driver@qlogic.com
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Dept-GELinuxNICDev@qlogic.com
+M:     Harish Patil <harish.patil@cavium.com>
+M:     Manish Chopra <manish.chopra@cavium.com>
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-M:     Harish Patil <harish.patil@qlogic.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@qlogic.com>
-M:     Dept-GELinuxNICDev@qlogic.com
-M:     linux-driver@qlogic.com
+M:     Harish Patil <harish.patil@cavium.com>
+M:     Manish Chopra <manish.chopra@cavium.com>
+M:     Dept-GELinuxNICDev@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlge/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Yuval Mintz <Yuval.Mintz@qlogic.com>
-M:     Ariel Elior <Ariel.Elior@qlogic.com>
-M:     everest-linux-l2@qlogic.com
+M:     Yuval Mintz <Yuval.Mintz@cavium.com>
+M:     Ariel Elior <Ariel.Elior@cavium.com>
+M:     everest-linux-l2@cavium.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qed/
index 512e47a..a2650f9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc3
 NAME = Psychotic Stoned Sheep
 
 # *DOCUMENTATION*
index d9ee817..940dfb4 100644 (file)
@@ -157,14 +157,16 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 static inline int
 read_int(struct task_struct *task, unsigned long addr, int * data)
 {
-       int copied = access_process_vm(task, addr, data, sizeof(int), 0);
+       int copied = access_process_vm(task, addr, data, sizeof(int),
+                       FOLL_FORCE);
        return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
 static inline int
 write_int(struct task_struct *task, unsigned long addr, int data)
 {
-       int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
+       int copied = access_process_vm(task, addr, &data, sizeof(int),
+                       FOLL_FORCE | FOLL_WRITE);
        return (copied == sizeof(int)) ? 0 : -EIO;
 }
 
@@ -281,7 +283,8 @@ long arch_ptrace(struct task_struct *child, long request,
        /* When I and D space are separate, these will need to be fixed.  */
        case PTRACE_PEEKTEXT: /* read word at location addr. */
        case PTRACE_PEEKDATA:
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+               copied = access_process_vm(child, addr, &tmp, sizeof(tmp),
+                               FOLL_FORCE);
                ret = -EIO;
                if (copied != sizeof(tmp))
                        break;
index ecd1237..bd204bf 100644 (file)
@@ -41,6 +41,8 @@ config ARC
        select PERF_USE_VMALLOC
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_GENERIC_DMA_COHERENT
+       select HAVE_KERNEL_GZIP
+       select HAVE_KERNEL_LZMA
 
 config MIGHT_HAVE_PCI
        bool
@@ -186,14 +188,6 @@ if SMP
 config ARC_HAS_COH_CACHES
        def_bool n
 
-config ARC_MCIP
-       bool "ARConnect Multicore IP (MCIP) Support "
-       depends on ISA_ARCV2
-       help
-         This IP block enables SMP in ARC-HS38 cores.
-         It provides for cross-core interrupts, multi-core debug
-         hardware semaphores, shared memory,....
-
 config NR_CPUS
        int "Maximum number of CPUs (2-4096)"
        range 2 4096
@@ -211,6 +205,15 @@ config ARC_SMP_HALT_ON_RESET
 
 endif  #SMP
 
+config ARC_MCIP
+       bool "ARConnect Multicore IP (MCIP) Support "
+       depends on ISA_ARCV2
+       default y if SMP
+       help
+         This IP block enables SMP in ARC-HS38 cores.
+         It provides for cross-core interrupts, multi-core debug
+         hardware semaphores, shared memory,....
+
 menuconfig ARC_CACHE
        bool "Enable Cache Support"
        default y
@@ -537,14 +540,6 @@ config ARC_DBG_TLB_PARANOIA
        bool "Paranoia Checks in Low Level TLB Handlers"
        default n
 
-config ARC_DBG_TLB_MISS_COUNT
-       bool "Profile TLB Misses"
-       default n
-       select DEBUG_FS
-       help
-         Counts number of I and D TLB Misses and exports them via Debugfs
-         The counters can be cleared via Debugfs as well
-
 endif
 
 config ARC_UBOOT_SUPPORT
index aa82d13..864adad 100644 (file)
@@ -50,9 +50,6 @@ atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
 
 cflags-$(atleast_gcc44)                        += -fsection-anchors
 
-cflags-$(CONFIG_ARC_HAS_LLSC)          += -mlock
-cflags-$(CONFIG_ARC_HAS_SWAPE)         += -mswape
-
 ifdef CONFIG_ISA_ARCV2
 
 ifndef CONFIG_ARC_HAS_LL64
index e597cb3..f94cf15 100644 (file)
@@ -14,9 +14,15 @@ UIMAGE_ENTRYADDR   = $(LINUX_START_TEXT)
 
 suffix-y := bin
 suffix-$(CONFIG_KERNEL_GZIP)   := gz
+suffix-$(CONFIG_KERNEL_LZMA)   := lzma
 
-targets += uImage uImage.bin uImage.gz
-extra-y += vmlinux.bin vmlinux.bin.gz
+targets += uImage
+targets += uImage.bin
+targets += uImage.gz
+targets += uImage.lzma
+extra-y += vmlinux.bin
+extra-y += vmlinux.bin.gz
+extra-y += vmlinux.bin.lzma
 
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
@@ -24,12 +30,18 @@ $(obj)/vmlinux.bin: vmlinux FORCE
 $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
        $(call if_changed,gzip)
 
+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,lzma)
+
 $(obj)/uImage.bin: $(obj)/vmlinux.bin FORCE
        $(call if_changed,uimage,none)
 
 $(obj)/uImage.gz: $(obj)/vmlinux.bin.gz FORCE
        $(call if_changed,uimage,gzip)
 
+$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma FORCE
+       $(call if_changed,uimage,lzma)
+
 $(obj)/uImage: $(obj)/uImage.$(suffix-y)
        @ln -sf $(notdir $<) $@
        @echo '  Image $@ is ready'
index db25c65..7f3f9f6 100644 (file)
@@ -349,10 +349,11 @@ struct cpuinfo_arc {
        struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
        struct bcr_isa isa;
+       const char *details, *name;
        unsigned int vec_base;
        struct cpuinfo_arc_ccm iccm, dccm;
        struct {
-               unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
+               unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
                             fpu_sp:1, fpu_dp:1, pad2:6,
                             debug:1, ap:1, smart:1, rtt:1, pad3:4,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
index fb781e3..b3410ff 100644 (file)
@@ -53,7 +53,7 @@ extern void arc_cache_init(void);
 extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
 extern void read_decode_cache_bcr(void);
 
-extern int ioc_exists;
+extern int ioc_enable;
 extern unsigned long perip_base, perip_end;
 
 #endif /* !__ASSEMBLY__ */
index 7096f97..aa2d6da 100644 (file)
@@ -54,7 +54,7 @@ extern int elf_check_arch(const struct elf32_hdr *);
  * the loader.  We need to make sure that it is out of the way of the program
  * that it will "exec", and that there is sufficient room for the brk.
  */
-#define ELF_ET_DYN_BASE                (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE                (2UL * TASK_SIZE / 3)
 
 /*
  * When the program starts, a1 contains a pointer to a function to be
index 847e3bb..c8fbe41 100644 (file)
@@ -55,6 +55,22 @@ struct mcip_cmd {
 #define IDU_M_DISTRI_DEST              0x2
 };
 
+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,
+                            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;
+#endif
+};
+
 /*
  * MCIP programming model
  *
index 518222b..6e91d8b 100644 (file)
@@ -18,6 +18,7 @@
 struct mod_arch_specific {
        void *unw_info;
        int unw_sec_idx;
+       const char *secstr;
 };
 #endif
 
index 48b37c6..cb954cd 100644 (file)
@@ -27,11 +27,6 @@ struct id_to_str {
        const char *str;
 };
 
-struct cpuinfo_data {
-       struct id_to_str info;
-       int up_range;
-};
-
 extern int root_mountflags, end_mem;
 
 void setup_processor(void);
@@ -43,5 +38,6 @@ void __init setup_arch_memory(void);
 #define IS_USED_RUN(v)         ((v) ? "" : "(not used) ")
 #define IS_USED_CFG(cfg)       IS_USED_RUN(IS_ENABLED(cfg))
 #define IS_AVAIL2(v, s, cfg)   IS_AVAIL1(v, s), IS_AVAIL1(v, IS_USED_CFG(cfg))
+#define IS_AVAIL3(v, v2, s)    IS_AVAIL1(v, s), IS_AVAIL1(v, IS_DISABLED_RUN(v2))
 
 #endif /* __ASMARC_SETUP_H */
index e56f9fc..772b67c 100644 (file)
@@ -17,6 +17,7 @@ int sys_clone_wrapper(int, int, int, int, int);
 int sys_cacheflush(uint32_t, uint32_t uint32_t);
 int sys_arc_settls(void *);
 int sys_arc_gettls(void);
+int sys_arc_usr_cmpxchg(int *, int, int);
 
 #include <asm-generic/syscalls.h>
 
index 41fa2ec..9a34136 100644 (file)
 
 #define NR_syscalls    __NR_syscalls
 
+/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
+#define __NR_sysfs             (__NR_arch_specific_syscall + 3)
+
 /* ARC specific syscall */
 #define __NR_cacheflush                (__NR_arch_specific_syscall + 0)
 #define __NR_arc_settls                (__NR_arch_specific_syscall + 1)
 #define __NR_arc_gettls                (__NR_arch_specific_syscall + 2)
+#define __NR_arc_usr_cmpxchg   (__NR_arch_specific_syscall + 4)
 
 __SYSCALL(__NR_cacheflush, sys_cacheflush)
 __SYSCALL(__NR_arc_settls, sys_arc_settls)
 __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
-
-
-/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
-#define __NR_sysfs             (__NR_arch_specific_syscall + 3)
+__SYSCALL(__NR_arc_usr_cmpxchg, sys_arc_usr_cmpxchg)
 __SYSCALL(__NR_sysfs, sys_sysfs)
 
 #undef __SYSCALL
index 72f9179..c424d5a 100644 (file)
 #include <asm/mcip.h>
 #include <asm/setup.h>
 
-static char smp_cpuinfo_buf[128];
-static int idu_detected;
-
 static DEFINE_RAW_SPINLOCK(mcip_lock);
 
+#ifdef CONFIG_SMP
+
+static char smp_cpuinfo_buf[128];
+
 static void mcip_setup_per_cpu(int cpu)
 {
        smp_ipi_irq_setup(cpu, IPI_IRQ);
@@ -86,21 +87,7 @@ static void mcip_ipi_clear(int irq)
 
 static void mcip_probe_n_setup(void)
 {
-       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,
-                            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;
-#endif
-       } mp;
+       struct mcip_bcr mp;
 
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
@@ -114,7 +101,6 @@ static void mcip_probe_n_setup(void)
                IS_AVAIL1(mp.gfrc, "GFRC"));
 
        cpuinfo_arc700[0].extn.gfrc = mp.gfrc;
-       idu_detected = mp.idu;
 
        if (mp.dbg) {
                __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
@@ -130,6 +116,8 @@ struct plat_smp_ops plat_smp_ops = {
        .ipi_clear      = mcip_ipi_clear,
 };
 
+#endif
+
 /***************************************************************************
  * ARCv2 Interrupt Distribution Unit (IDU)
  *
@@ -295,8 +283,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
        /* Read IDU BCR to confirm nr_irqs */
        int nr_irqs = of_irq_count(intc);
        int i, irq;
+       struct mcip_bcr mp;
+
+       READ_BCR(ARC_REG_MCIP_BCR, mp);
 
-       if (!idu_detected)
+       if (!mp.idu)
                panic("IDU not detected, but DeviceTree using it");
 
        pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
index 9a28497..42e964d 100644 (file)
@@ -30,17 +30,9 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
                              char *secstr, struct module *mod)
 {
 #ifdef CONFIG_ARC_DW2_UNWIND
-       int i;
-
        mod->arch.unw_sec_idx = 0;
        mod->arch.unw_info = NULL;
-
-       for (i = 1; i < hdr->e_shnum; i++) {
-               if (strcmp(secstr+sechdrs[i].sh_name, ".eh_frame") == 0) {
-                       mod->arch.unw_sec_idx = i;
-                       break;
-               }
-       }
+       mod->arch.secstr = secstr;
 #endif
        return 0;
 }
@@ -59,29 +51,33 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
                       unsigned int relsec,     /* sec index for relo sec */
                       struct module *module)
 {
-       int i, n;
+       int i, n, relo_type;
        Elf32_Rela *rel_entry = (void *)sechdrs[relsec].sh_addr;
        Elf32_Sym *sym_entry, *sym_sec;
-       Elf32_Addr relocation;
-       Elf32_Addr location;
-       Elf32_Addr sec_to_patch;
-       int relo_type;
-
-       sec_to_patch = sechdrs[sechdrs[relsec].sh_info].sh_addr;
+       Elf32_Addr relocation, location, tgt_addr;
+       unsigned int tgtsec;
+
+       /*
+        * @relsec has relocations e.g. .rela.init.text
+        * @tgtsec is section to patch e.g. .init.text
+        */
+       tgtsec = sechdrs[relsec].sh_info;
+       tgt_addr = sechdrs[tgtsec].sh_addr;
        sym_sec = (Elf32_Sym *) sechdrs[symindex].sh_addr;
        n = sechdrs[relsec].sh_size / sizeof(*rel_entry);
 
-       pr_debug("\n========== Module Sym reloc ===========================\n");
-       pr_debug("Section to fixup %x\n", sec_to_patch);
+       pr_debug("\nSection to fixup %s @%x\n",
+                module->arch.secstr + sechdrs[tgtsec].sh_name, tgt_addr);
        pr_debug("=========================================================\n");
-       pr_debug("rela->r_off | rela->addend | sym->st_value | ADDR | VALUE\n");
+       pr_debug("r_off\tr_add\tst_value ADDRESS  VALUE\n");
        pr_debug("=========================================================\n");
 
        /* Loop thru entries in relocation section */
        for (i = 0; i < n; i++) {
+               const char *s;
 
                /* This is where to make the change */
-               location = sec_to_patch + rel_entry[i].r_offset;
+               location = tgt_addr + rel_entry[i].r_offset;
 
                /* This is the symbol it is referring to.  Note that all
                   undefined symbols have been resolved.  */
@@ -89,10 +85,15 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 
                relocation = sym_entry->st_value + rel_entry[i].r_addend;
 
-               pr_debug("\t%x\t\t%x\t\t%x  %x %x [%s]\n",
-                       rel_entry[i].r_offset, rel_entry[i].r_addend,
-                       sym_entry->st_value, location, relocation,
-                       strtab + sym_entry->st_name);
+               if (sym_entry->st_name == 0 && ELF_ST_TYPE (sym_entry->st_info) == STT_SECTION) {
+                       s = module->arch.secstr + sechdrs[sym_entry->st_shndx].sh_name;
+               } else {
+                       s = strtab + sym_entry->st_name;
+               }
+
+               pr_debug("   %x\t%x\t%x %x %x [%s]\n",
+                        rel_entry[i].r_offset, rel_entry[i].r_addend,
+                        sym_entry->st_value, location, relocation, s);
 
                /* This assumes modules are built with -mlong-calls
                 * so any branches/jumps are absolute 32 bit jmps
@@ -111,6 +112,10 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
                        goto relo_err;
 
        }
+
+       if (strcmp(module->arch.secstr+sechdrs[tgtsec].sh_name, ".eh_frame") == 0)
+               module->arch.unw_sec_idx = tgtsec;
+
        return 0;
 
 relo_err:
index be1972b..59aa43c 100644 (file)
@@ -41,6 +41,39 @@ SYSCALL_DEFINE0(arc_gettls)
        return task_thread_info(current)->thr_ptr;
 }
 
+SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
+{
+       int uval;
+       int ret;
+
+       /*
+        * This is only for old cores lacking LLOCK/SCOND, which by defintion
+        * can't possibly be SMP. Thus doesn't need to be SMP safe.
+        * And this also helps reduce the overhead for serializing in
+        * the UP case
+        */
+       WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP));
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       preempt_disable();
+
+       ret = __get_user(uval, uaddr);
+       if (ret)
+               goto done;
+
+       if (uval != expected)
+               ret = -EAGAIN;
+       else
+               ret = __put_user(new, uaddr);
+
+done:
+       preempt_enable();
+
+       return ret;
+}
+
 void arch_cpu_idle(void)
 {
        /* sleep, but enable all interrupts before committing */
index 3df7f9c..0385df7 100644 (file)
@@ -40,6 +40,29 @@ struct task_struct *_current_task[NR_CPUS];  /* For stack switching */
 
 struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 
+static const struct id_to_str arc_cpu_rel[] = {
+#ifdef CONFIG_ISA_ARCOMPACT
+       { 0x34, "R4.10"},
+       { 0x35, "R4.11"},
+#else
+       { 0x51, "R2.0" },
+       { 0x52, "R2.1" },
+       { 0x53, "R3.0" },
+#endif
+       { 0x00, NULL   }
+};
+
+static const struct id_to_str arc_cpu_nm[] = {
+#ifdef CONFIG_ISA_ARCOMPACT
+       { 0x20, "ARC 600"   },
+       { 0x30, "ARC 770"   },  /* 750 identified seperately */
+#else
+       { 0x40, "ARC EM"  },
+       { 0x50, "ARC HS38"  },
+#endif
+       { 0x00, "Unknown"   }
+};
+
 static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu)
 {
        if (is_isa_arcompact()) {
@@ -92,11 +115,26 @@ static void read_arc_build_cfg_regs(void)
        struct bcr_timer timer;
        struct bcr_generic bcr;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+       const struct id_to_str *tbl;
+
        FIX_PTR(cpu);
 
        READ_BCR(AUX_IDENTITY, cpu->core);
        READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
 
+       for (tbl = &arc_cpu_rel[0]; tbl->id != 0; tbl++) {
+               if (cpu->core.family == tbl->id) {
+                       cpu->details = tbl->str;
+                       break;
+               }
+       }
+
+       for (tbl = &arc_cpu_nm[0]; tbl->id != 0; tbl++) {
+               if ((cpu->core.family & 0xF0) == tbl->id)
+                       break;
+       }
+       cpu->name = tbl->str;
+
        READ_BCR(ARC_REG_TIMERS_BCR, timer);
        cpu->extn.timer0 = timer.t0;
        cpu->extn.timer1 = timer.t1;
@@ -111,6 +149,9 @@ static void read_arc_build_cfg_regs(void)
        cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0;        /* 1,3 */
        cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
        cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
+       cpu->extn.swape = (cpu->core.family >= 0x34) ? 1 :
+                               IS_ENABLED(CONFIG_ARC_HAS_SWAPE);
+
        READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem);
 
        /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */
@@ -160,64 +201,38 @@ static void read_arc_build_cfg_regs(void)
        cpu->extn.rtt = bcr.ver ? 1 : 0;
 
        cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
-}
 
-static const struct cpuinfo_data arc_cpu_tbl[] = {
-#ifdef CONFIG_ISA_ARCOMPACT
-       { {0x20, "ARC 600"      }, 0x2F},
-       { {0x30, "ARC 700"      }, 0x33},
-       { {0x34, "ARC 700 R4.10"}, 0x34},
-       { {0x35, "ARC 700 R4.11"}, 0x35},
-#else
-       { {0x50, "ARC HS38 R2.0"}, 0x51},
-       { {0x52, "ARC HS38 R2.1"}, 0x52},
-       { {0x53, "ARC HS38 R3.0"}, 0x53},
-#endif
-       { {0x00, NULL           } }
-};
+       /* some hacks for lack of feature BCR info in old ARC700 cores */
+       if (is_isa_arcompact()) {
+               if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
+                       cpu->isa.atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
+               else
+                       cpu->isa.atomic = cpu->isa.atomic1;
 
+               cpu->isa.be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
+
+                /* there's no direct way to distinguish 750 vs. 770 */
+               if (unlikely(cpu->core.family < 0x34 || cpu->mmu.ver < 3))
+                       cpu->name = "ARC750";
+       }
+}
 
 static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 {
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
        struct bcr_identity *core = &cpu->core;
-       const struct cpuinfo_data *tbl;
-       char *isa_nm;
-       int i, be, atomic;
-       int n = 0;
+       int i, n = 0;
 
        FIX_PTR(cpu);
 
-       if (is_isa_arcompact()) {
-               isa_nm = "ARCompact";
-               be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
-
-               atomic = cpu->isa.atomic1;
-               if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
-                       atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
-       } else {
-               isa_nm = "ARCv2";
-               be = cpu->isa.be;
-               atomic = cpu->isa.atomic;
-       }
-
        n += scnprintf(buf + n, len - n,
                       "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
                       core->family, core->cpu_id, core->chip_id);
 
-       for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
-               if ((core->family >= tbl->info.id) &&
-                   (core->family <= tbl->up_range)) {
-                       n += scnprintf(buf + n, len - n,
-                                      "processor [%d]\t: %s (%s ISA) %s\n",
-                                      cpu_id, tbl->info.str, isa_nm,
-                                      IS_AVAIL1(be, "[Big-Endian]"));
-                       break;
-               }
-       }
-
-       if (tbl->info.id == 0)
-               n += scnprintf(buf + n, len - n, "UNKNOWN ARC Processor\n");
+       n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s\n",
+                      cpu_id, cpu->name, cpu->details,
+                      is_isa_arcompact() ? "ARCompact" : "ARCv2",
+                      IS_AVAIL1(cpu->isa.be, "[Big-Endian]"));
 
        n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
                       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
@@ -226,7 +241,7 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                                 CONFIG_ARC_HAS_RTC));
 
        n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
-                          IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
+                          IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
                           IS_AVAIL2(cpu->isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64),
                           IS_AVAIL1(cpu->isa.unalign, "unalign (not used)"));
 
@@ -253,7 +268,7 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       IS_AVAIL1(cpu->extn.swap, "swap "),
                       IS_AVAIL1(cpu->extn.minmax, "minmax "),
                       IS_AVAIL1(cpu->extn.crc, "crc "),
-                      IS_AVAIL2(1, "swape", CONFIG_ARC_HAS_SWAPE));
+                      IS_AVAIL2(cpu->extn.swape, "swape", CONFIG_ARC_HAS_SWAPE));
 
        if (cpu->bpu.ver)
                n += scnprintf(buf + n, len - n,
@@ -272,9 +287,7 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 
        FIX_PTR(cpu);
 
-       n += scnprintf(buf + n, len - n,
-                      "Vector Table\t: %#x\nPeripherals\t: %#lx:%#lx\n",
-                      cpu->vec_base, perip_base, perip_end);
+       n += scnprintf(buf + n, len - n, "Vector Table\t: %#x\n", cpu->vec_base);
 
        if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
                n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
@@ -507,7 +520,7 @@ static void *c_start(struct seq_file *m, loff_t *pos)
         * way to pass it w/o having to kmalloc/free a 2 byte string.
         * Encode cpu-id as 0xFFcccc, which is decoded by show routine.
         */
-       return *pos < num_possible_cpus() ? cpu_to_ptr(*pos) : NULL;
+       return *pos < nr_cpu_ids ? cpu_to_ptr(*pos) : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
index 934150e..82f9bc8 100644 (file)
@@ -237,113 +237,3 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
        if (!user_mode(regs))
                show_stacktrace(current, regs);
 }
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/mount.h>
-#include <linux/pagemap.h>
-#include <linux/init.h>
-#include <linux/namei.h>
-#include <linux/debugfs.h>
-
-static struct dentry *test_dentry;
-static struct dentry *test_dir;
-static struct dentry *test_u32_dentry;
-
-static u32 clr_on_read = 1;
-
-#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
-u32 numitlb, numdtlb, num_pte_not_present;
-
-static int fill_display_data(char *kbuf)
-{
-       size_t num = 0;
-       num += sprintf(kbuf + num, "I-TLB Miss %x\n", numitlb);
-       num += sprintf(kbuf + num, "D-TLB Miss %x\n", numdtlb);
-       num += sprintf(kbuf + num, "PTE not present %x\n", num_pte_not_present);
-
-       if (clr_on_read)
-               numitlb = numdtlb = num_pte_not_present = 0;
-
-       return num;
-}
-
-static int tlb_stats_open(struct inode *inode, struct file *file)
-{
-       file->private_data = (void *)__get_free_page(GFP_KERNEL);
-       return 0;
-}
-
-/* called on user read(): display the counters */
-static ssize_t tlb_stats_output(struct file *file,     /* file descriptor */
-                               char __user *user_buf,  /* user buffer */
-                               size_t len,             /* length of buffer */
-                               loff_t *offset)         /* offset in the file */
-{
-       size_t num;
-       char *kbuf = (char *)file->private_data;
-
-       /* All of the data can he shoved in one iteration */
-       if (*offset != 0)
-               return 0;
-
-       num = fill_display_data(kbuf);
-
-       /* simple_read_from_buffer() is helper for copy to user space
-          It copies up to @2 (num) bytes from kernel buffer @4 (kbuf) at offset
-          @3 (offset) into the user space address starting at @1 (user_buf).
-          @5 (len) is max size of user buffer
-        */
-       return simple_read_from_buffer(user_buf, num, offset, kbuf, len);
-}
-
-/* called on user write : clears the counters */
-static ssize_t tlb_stats_clear(struct file *file, const char __user *user_buf,
-                              size_t length, loff_t *offset)
-{
-       numitlb = numdtlb = num_pte_not_present = 0;
-       return length;
-}
-
-static int tlb_stats_close(struct inode *inode, struct file *file)
-{
-       free_page((unsigned long)(file->private_data));
-       return 0;
-}
-
-static const struct file_operations tlb_stats_file_ops = {
-       .read = tlb_stats_output,
-       .write = tlb_stats_clear,
-       .open = tlb_stats_open,
-       .release = tlb_stats_close
-};
-#endif
-
-static int __init arc_debugfs_init(void)
-{
-       test_dir = debugfs_create_dir("arc", NULL);
-
-#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
-       test_dentry = debugfs_create_file("tlb_stats", 0444, test_dir, NULL,
-                                         &tlb_stats_file_ops);
-#endif
-
-       test_u32_dentry =
-           debugfs_create_u32("clr_on_read", 0444, test_dir, &clr_on_read);
-
-       return 0;
-}
-
-module_init(arc_debugfs_init);
-
-static void __exit arc_debugfs_exit(void)
-{
-       debugfs_remove(test_u32_dentry);
-       debugfs_remove(test_dentry);
-       debugfs_remove(test_dir);
-}
-module_exit(arc_debugfs_exit);
-
-#endif
index 97dddbe..2b96cfc 100644 (file)
@@ -22,8 +22,8 @@
 #include <asm/setup.h>
 
 static int l2_line_sz;
-int ioc_exists;
-volatile int slc_enable = 1, ioc_enable = 1;
+static int ioc_exists;
+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 */
 
@@ -53,18 +53,15 @@ char *arc_cache_mumbojumbo(int c, char *buf, int len)
        PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache");
        PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
 
-       if (!is_isa_arcv2())
-                return buf;
-
        p = &cpuinfo_arc700[c].slc;
        if (p->ver)
                n += scnprintf(buf + n, len - n,
                               "SLC\t\t: %uK, %uB Line%s\n",
                               p->sz_k, p->line_len, IS_USED_RUN(slc_enable));
 
-       if (ioc_exists)
-               n += scnprintf(buf + n, len - n, "IOC\t\t:%s\n",
-                               IS_DISABLED_RUN(ioc_enable));
+       n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n",
+                      perip_base,
+                      IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency "));
 
        return buf;
 }
@@ -113,8 +110,10 @@ static void read_decode_cache_bcr_arcv2(int cpu)
        }
 
        READ_BCR(ARC_REG_CLUSTER_BCR, cbcr);
-       if (cbcr.c && ioc_enable)
+       if (cbcr.c)
                ioc_exists = 1;
+       else
+               ioc_enable = 0;
 
        /* HS 2.0 didn't have AUX_VOL */
        if (cpuinfo_arc700[cpu].core.family > 0x51) {
@@ -1002,7 +1001,7 @@ void arc_cache_init(void)
                        read_aux_reg(ARC_REG_SLC_CTRL) | SLC_CTRL_DISABLE);
        }
 
-       if (is_isa_arcv2() && ioc_exists) {
+       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 */
index 20afc65..60aab5a 100644 (file)
@@ -45,7 +45,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
         *   -For coherent data, Read/Write to buffers terminate early in cache
         *   (vs. always going to memory - thus are faster)
         */
-       if ((is_isa_arcv2() && ioc_exists) ||
+       if ((is_isa_arcv2() && ioc_enable) ||
            (attrs & DMA_ATTR_NON_CONSISTENT))
                need_coh = 0;
 
@@ -97,7 +97,7 @@ static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
        int is_non_coh = 1;
 
        is_non_coh = (attrs & DMA_ATTR_NON_CONSISTENT) ||
-                       (is_isa_arcv2() && ioc_exists);
+                       (is_isa_arcv2() && ioc_enable);
 
        if (PageHighMem(page) || !is_non_coh)
                iounmap((void __force __iomem *)vaddr);
index ec868a9..bdb295e 100644 (file)
@@ -793,16 +793,16 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
        char super_pg[64] = "";
 
        if (p_mmu->s_pg_sz_m)
-               scnprintf(super_pg, 64, "%dM Super Page%s, ",
+               scnprintf(super_pg, 64, "%dM Super Page %s",
                          p_mmu->s_pg_sz_m,
                          IS_USED_CFG(CONFIG_TRANSPARENT_HUGEPAGE));
 
        n += scnprintf(buf + n, len - n,
-                     "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d %s%s\n",
+                     "MMU [v%x]\t: %dk PAGE, %sJTLB %d (%dx%d), uDTLB %d, uITLB %d%s%s\n",
                       p_mmu->ver, p_mmu->pg_sz_k, super_pg,
                       p_mmu->sets * p_mmu->ways, p_mmu->sets, p_mmu->ways,
                       p_mmu->u_dtlb, p_mmu->u_itlb,
-                      IS_AVAIL2(p_mmu->pae, "PAE40 ", CONFIG_ARC_HAS_PAE40));
+                      IS_AVAIL2(p_mmu->pae, "PAE40 ", CONFIG_ARC_HAS_PAE40));
 
        return buf;
 }
index f1967ee..b30e4e3 100644 (file)
@@ -237,15 +237,6 @@ ex_saved_reg1:
 
 2:
 
-#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
-       and.f 0, r0, _PAGE_PRESENT
-       bz   1f
-       ld   r3, [num_pte_not_present]
-       add  r3, r3, 1
-       st   r3, [num_pte_not_present]
-1:
-#endif
-
 .endm
 
 ;-----------------------------------------------------------------
@@ -309,12 +300,6 @@ ENTRY(EV_TLBMissI)
 
        TLBMISS_FREEUP_REGS
 
-#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
-       ld  r0, [@numitlb]
-       add r0, r0, 1
-       st  r0, [@numitlb]
-#endif
-
        ;----------------------------------------------------------------
        ; Get the PTE corresponding to V-addr accessed, r2 is setup with EFA
        LOAD_FAULT_PTE
@@ -349,12 +334,6 @@ ENTRY(EV_TLBMissD)
 
        TLBMISS_FREEUP_REGS
 
-#ifdef CONFIG_ARC_DBG_TLB_MISS_COUNT
-       ld  r0, [@numdtlb]
-       add r0, r0, 1
-       st  r0, [@numdtlb]
-#endif
-
        ;----------------------------------------------------------------
        ; Get the PTE corresponding to V-addr accessed
        ; If PTE exists, it will setup, r0 = PTE, r1 = Ptr to PTE, r2 = EFA
index b3df1c6..386eee6 100644 (file)
                        arm,primecell-periphid = <0x10480180>;
                        max-frequency = <100000000>;
                        bus-width = <4>;
+                       cap-sd-highspeed;
                        cap-mmc-highspeed;
+                       sd-uhs-sdr12;
+                       sd-uhs-sdr25;
+                       /* All direction control is used */
+                       st,sig-dir-cmd;
+                       st,sig-dir-dat0;
+                       st,sig-dir-dat2;
+                       st,sig-dir-dat31;
+                       st,sig-pin-fbclk;
+                       full-pwr-cycle;
                        vmmc-supply = <&ab8500_ldo_aux3_reg>;
                        vqmmc-supply = <&vmmci>;
                        pinctrl-names = "default", "sleep";
                        pinctrl-0 = <&sdi0_default_mode>;
                        pinctrl-1 = <&sdi0_sleep_mode>;
 
-                       cd-gpios  = <&gpio6 26 GPIO_ACTIVE_LOW>; // 218
+                       /* GPIO218 MMC_CD */
+                       cd-gpios  = <&gpio6 26 GPIO_ACTIVE_LOW>;
 
                        status = "okay";
                };
                                        /* VMMCI level-shifter enable */
                                        snowball_cfg3 {
                                                pins = "GPIO217_AH12";
-                                               ste,config = <&gpio_out_lo>;
+                                               ste,config = <&gpio_out_hi>;
                                        };
                                        /* VMMCI level-shifter voltage select */
                                        snowball_cfg4 {
index 2c49c36..5357ea9 100644 (file)
 };
 
 &mio_clk {
-       compatible = "socionext,uniphier-pro5-mio-clock";
+       compatible = "socionext,uniphier-pro5-sd-clock";
 };
 
 &mio_rst {
-       compatible = "socionext,uniphier-pro5-mio-reset";
+       compatible = "socionext,uniphier-pro5-sd-reset";
 };
 
 &peri_clk {
index 8789cd5..950f07b 100644 (file)
 };
 
 &mio_clk {
-       compatible = "socionext,uniphier-pxs2-mio-clock";
+       compatible = "socionext,uniphier-pxs2-sd-clock";
 };
 
 &mio_rst {
-       compatible = "socionext,uniphier-pxs2-mio-reset";
+       compatible = "socionext,uniphier-pxs2-sd-reset";
 };
 
 &peri_clk {
index a3824e6..d7fdb2a 100644 (file)
@@ -70,7 +70,7 @@
                        global_timer: timer@40002200 {
                                compatible = "arm,cortex-a9-global-timer";
                                reg = <0x40002200 0x20>;
-                               interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
                                interrupt-parent = <&intc>;
                                clocks = <&clks VF610_CLK_PLATFORM_BUS>;
                        };
index 437d074..11f37ed 100644 (file)
@@ -850,6 +850,7 @@ CONFIG_PWM_SUN4I=y
 CONFIG_PWM_TEGRA=y
 CONFIG_PWM_VT8500=y
 CONFIG_PHY_HIX5HD2_SATA=y
+CONFIG_E1000E=y
 CONFIG_PWM_STI=y
 CONFIG_PWM_BCM2835=y
 CONFIG_PWM_BRCMSTB=m
index 194b699..ada0d29 100644 (file)
@@ -19,7 +19,7 @@
  * This may need to be greater than __NR_last_syscall+1 in order to
  * account for the padding in the syscall table
  */
-#define __NR_syscalls  (396)
+#define __NR_syscalls  (400)
 
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
index 2cb9dc7..314100a 100644 (file)
 #define __NR_copy_file_range           (__NR_SYSCALL_BASE+391)
 #define __NR_preadv2                   (__NR_SYSCALL_BASE+392)
 #define __NR_pwritev2                  (__NR_SYSCALL_BASE+393)
+#define __NR_pkey_mprotect             (__NR_SYSCALL_BASE+394)
+#define __NR_pkey_alloc                        (__NR_SYSCALL_BASE+395)
+#define __NR_pkey_free                 (__NR_SYSCALL_BASE+396)
 
 /*
  * The following SWIs are ARM private.
index 703fa0f..08030b1 100644 (file)
                CALL(sys_copy_file_range)
                CALL(sys_preadv2)
                CALL(sys_pwritev2)
+               CALL(sys_pkey_mprotect)
+/* 395 */      CALL(sys_pkey_alloc)
+               CALL(sys_pkey_free)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 03e9273..08bb84f 100644 (file)
@@ -1312,6 +1312,13 @@ static int init_hyp_mode(void)
                goto out_err;
        }
 
+       err = create_hyp_mappings(kvm_ksym_ref(__bss_start),
+                                 kvm_ksym_ref(__bss_stop), PAGE_HYP_RO);
+       if (err) {
+               kvm_err("Cannot map bss section\n");
+               goto out_err;
+       }
+
        /*
         * Map the Hyp stack pages
         */
index 0df062d..b54db47 100644 (file)
@@ -408,7 +408,7 @@ static struct genpd_onecell_data imx_gpc_onecell_data = {
 static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
 {
        struct clk *clk;
-       int i;
+       int i, ret;
 
        imx6q_pu_domain.reg = pu_reg;
 
@@ -430,13 +430,22 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
        if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
                return 0;
 
-       pm_genpd_init(&imx6q_pu_domain.base, NULL, false);
-       return of_genpd_add_provider_onecell(dev->of_node,
+       for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
+               pm_genpd_init(imx_gpc_domains[i], NULL, false);
+
+       ret =  of_genpd_add_provider_onecell(dev->of_node,
                                             &imx_gpc_onecell_data);
+       if (ret)
+               goto power_off;
+
+       return 0;
 
+power_off:
+       imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
 clk_err:
        while (i--)
                clk_put(imx6q_pu_domain.clk[i]);
+       imx6q_pu_domain.reg = NULL;
        return -EINVAL;
 }
 
index 97fd251..45801b2 100644 (file)
@@ -173,7 +173,7 @@ static void __init imx6q_enet_phy_init(void)
                                ksz9021rn_phy_fixup);
                phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
                                ksz9031rn_phy_fixup);
-               phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+               phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
                                ar8031_phy_fixup);
                phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
                                ar8035_phy_fixup);
index f9b6bd3..541647f 100644 (file)
@@ -23,6 +23,7 @@ config MACH_MVEBU_V7
        select CACHE_L2X0
        select ARM_CPU_SUSPEND
        select MACH_MVEBU_ANY
+       select MVEBU_CLK_COREDIV
 
 config MACH_ARMADA_370
        bool "Marvell Armada 370 boards"
@@ -32,7 +33,6 @@ config MACH_ARMADA_370
        select CPU_PJ4B
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_370
-       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 370 SoC with device tree.
@@ -50,7 +50,6 @@ config MACH_ARMADA_375
        select HAVE_SMP
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_375
-       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 375 SoC with device tree.
@@ -68,7 +67,6 @@ config MACH_ARMADA_38X
        select HAVE_SMP
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_38X
-       select MVEBU_CLK_COREDIV
        help
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 380/385 SoC with device tree.
index 82dddee..3930fbb 100644 (file)
@@ -1,6 +1,7 @@
 config ARCH_UNIPHIER
        bool "Socionext UniPhier SoCs"
        depends on ARCH_MULTI_V7
+       select ARCH_HAS_RESET_CONTROLLER
        select ARM_AMBA
        select ARM_GLOBAL_TIMER
        select ARM_GIC
index 6d8e8e3..4cdfab3 100644 (file)
@@ -7,7 +7,7 @@
  *        : r4 = aborted context pc
  *        : r5 = aborted context psr
  *
- * Returns : r4-r5, r10-r11, r13 preserved
+ * Returns : r4-r5, r9-r11, r13 preserved
  *
  * Purpose : obtain information about current aborted instruction.
  * Note: we read user space.  This means we might cause a data
@@ -48,7 +48,10 @@ ENTRY(v4t_late_abort)
 /* c */        b       do_DataAbort                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
 /* d */        b       do_DataAbort                    @ ldc   rd, [rn, #m]
 /* e */        b       .data_unknown
-/* f */
+/* f */        b       .data_unknown
+
+.data_unknown_r9:
+       ldr     r9, [sp], #4
 .data_unknown: @ Part of jumptable
        mov     r0, r4
        mov     r1, r8
@@ -57,6 +60,7 @@ ENTRY(v4t_late_abort)
 .data_arm_ldmstm:
        tst     r8, #1 << 21                    @ check writeback bit
        beq     do_DataAbort                    @ no writeback -> no fixup
+       str     r9, [sp, #-4]!
        mov     r7, #0x11
        orr     r7, r7, #0x1100
        and     r6, r8, r7
@@ -75,12 +79,14 @@ ENTRY(v4t_late_abort)
        subne   r7, r7, r6, lsl #2              @ Undo increment
        addeq   r7, r7, r6, lsl #2              @ Undo decrement
        str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
+       ldr     r9, [sp], #4
        b       do_DataAbort
 
 .data_arm_lateldrhpre:
        tst     r8, #1 << 21                    @ Check writeback bit
        beq     do_DataAbort                    @ No writeback -> no fixup
 .data_arm_lateldrhpost:
+       str     r9, [sp, #-4]!
        and     r9, r8, #0x00f                  @ get Rm / low nibble of immediate value
        tst     r8, #1 << 22                    @ if (immediate offset)
        andne   r6, r8, #0xf00                  @ { immediate high nibble
@@ -93,6 +99,7 @@ ENTRY(v4t_late_abort)
        subne   r7, r7, r6                      @ Undo incrmenet
        addeq   r7, r7, r6                      @ Undo decrement
        str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
+       ldr     r9, [sp], #4
        b       do_DataAbort
 
 .data_arm_lateldrpreconst:
@@ -101,12 +108,14 @@ ENTRY(v4t_late_abort)
 .data_arm_lateldrpostconst:
        movs    r6, r8, lsl #20                 @ Get offset
        beq     do_DataAbort                    @ zero -> no fixup
+       str     r9, [sp, #-4]!
        and     r9, r8, #15 << 16               @ Extract 'n' from instruction
        ldr     r7, [r2, r9, lsr #14]           @ Get register 'Rn'
        tst     r8, #1 << 23                    @ Check U bit
        subne   r7, r7, r6, lsr #20             @ Undo increment
        addeq   r7, r7, r6, lsr #20             @ Undo decrement
        str     r7, [r2, r9, lsr #14]           @ Put register 'Rn'
+       ldr     r9, [sp], #4
        b       do_DataAbort
 
 .data_arm_lateldrprereg:
@@ -115,6 +124,7 @@ ENTRY(v4t_late_abort)
 .data_arm_lateldrpostreg:
        and     r7, r8, #15                     @ Extract 'm' from instruction
        ldr     r6, [r2, r7, lsl #2]            @ Get register 'Rm'
+       str     r9, [sp, #-4]!
        mov     r9, r8, lsr #7                  @ get shift count
        ands    r9, r9, #31
        and     r7, r8, #0x70                   @ get shift type
@@ -126,33 +136,33 @@ ENTRY(v4t_late_abort)
        b       .data_arm_apply_r6_and_rn
        b       .data_arm_apply_r6_and_rn       @ 1: LSL #0
        nop
-       b       .data_unknown                   @ 2: MUL?
+       b       .data_unknown_r9                @ 2: MUL?
        nop
-       b       .data_unknown                   @ 3: MUL?
+       b       .data_unknown_r9                @ 3: MUL?
        nop
        mov     r6, r6, lsr r9                  @ 4: LSR #!0
        b       .data_arm_apply_r6_and_rn
        mov     r6, r6, lsr #32                 @ 5: LSR #32
        b       .data_arm_apply_r6_and_rn
-       b       .data_unknown                   @ 6: MUL?
+       b       .data_unknown_r9                @ 6: MUL?
        nop
-       b       .data_unknown                   @ 7: MUL?
+       b       .data_unknown_r9                @ 7: MUL?
        nop
        mov     r6, r6, asr r9                  @ 8: ASR #!0
        b       .data_arm_apply_r6_and_rn
        mov     r6, r6, asr #32                 @ 9: ASR #32
        b       .data_arm_apply_r6_and_rn
-       b       .data_unknown                   @ A: MUL?
+       b       .data_unknown_r9                @ A: MUL?
        nop
-       b       .data_unknown                   @ B: MUL?
+       b       .data_unknown_r9                @ B: MUL?
        nop
        mov     r6, r6, ror r9                  @ C: ROR #!0
        b       .data_arm_apply_r6_and_rn
        mov     r6, r6, rrx                     @ D: RRX
        b       .data_arm_apply_r6_and_rn
-       b       .data_unknown                   @ E: MUL?
+       b       .data_unknown_r9                @ E: MUL?
        nop
-       b       .data_unknown                   @ F: MUL?
+       b       .data_unknown_r9                @ F: MUL?
 
 .data_thumb_abort:
        ldrh    r8, [r4]                        @ read instruction
@@ -190,6 +200,7 @@ ENTRY(v4t_late_abort)
 .data_thumb_pushpop:
        tst     r8, #1 << 10
        beq     .data_unknown
+       str     r9, [sp, #-4]!
        and     r6, r8, #0x55                   @ hweight8(r8) + R bit
        and     r9, r8, #0xaa
        add     r6, r6, r9, lsr #1
@@ -204,9 +215,11 @@ ENTRY(v4t_late_abort)
        addeq   r7, r7, r6, lsl #2              @ increment SP if PUSH
        subne   r7, r7, r6, lsl #2              @ decrement SP if POP
        str     r7, [r2, #13 << 2]
+       ldr     r9, [sp], #4
        b       do_DataAbort
 
 .data_thumb_ldmstm:
+       str     r9, [sp, #-4]!
        and     r6, r8, #0x55                   @ hweight8(r8)
        and     r9, r8, #0xaa
        add     r6, r6, r9, lsr #1
@@ -219,4 +232,5 @@ ENTRY(v4t_late_abort)
        and     r6, r6, #15                     @ number of regs to transfer
        sub     r7, r7, r6, lsl #2              @ always decrement
        str     r7, [r2, r9, lsr #6]
+       ldr     r9, [sp], #4
        b       do_DataAbort
index 30398db..969ef88 100644 (file)
@@ -915,7 +915,7 @@ config RANDOMIZE_BASE
 
 config RANDOMIZE_MODULE_REGION_FULL
        bool "Randomize the module region independently from the core kernel"
-       depends on RANDOMIZE_BASE
+       depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE
        default y
        help
          Randomizes the location of the module region without considering the
index cfbdf02..101794f 100644 (file)
@@ -190,6 +190,7 @@ config ARCH_THUNDER
 
 config ARCH_UNIPHIER
        bool "Socionext UniPhier SoC Family"
+       select ARCH_HAS_RESET_CONTROLLER
        select PINCTRL
        help
          This enables support for Socionext UniPhier SoC family.
index ab51aed..3635b86 100644 (file)
@@ -15,7 +15,7 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
 GZFLAGS                :=-9
 
 ifneq ($(CONFIG_RELOCATABLE),)
-LDFLAGS_vmlinux                += -pie -Bsymbolic
+LDFLAGS_vmlinux                += -pie -shared -Bsymbolic
 endif
 
 ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
index 2d7872a..b09f3bc 100644 (file)
                nand-ecc-mode = "hw";
                nand-ecc-strength = <8>;
                nand-ecc-step-size = <512>;
+               nand-bus-width = <16>;
+               brcm,nand-oob-sector-size = <16>;
                #address-cells = <1>;
                #size-cells = <1>;
        };
index 220ac70..97d331e 100644 (file)
                             <1 14 0xf08>, /* Physical Non-Secure PPI */
                             <1 11 0xf08>, /* Virtual PPI */
                             <1 10 0xf08>; /* Hypervisor PPI */
+               fsl,erratum-a008585;
        };
 
        pmu {
index 337da90..7f0dc13 100644 (file)
                             <1 14 4>, /* Physical Non-Secure PPI, active-low */
                             <1 11 4>, /* Virtual PPI, active-low */
                             <1 10 4>; /* Hypervisor PPI, active-low */
+               fsl,erratum-a008585;
        };
 
        pmu {
index e5e3ed6..602e2c2 100644 (file)
                                #address-cells = <0x1>;
                                #size-cells = <0x0>;
                                cell-index = <1>;
-                               clocks = <&cpm_syscon0 0 3>;
+                               clocks = <&cpm_syscon0 1 21>;
                                status = "disabled";
                        };
 
index 46cdddf..e5eeca2 100644 (file)
        cap-mmc-highspeed;
        clock-frequency = <150000000>;
        disable-wp;
-       keep-power-in-suspend;
        non-removable;
        num-slots = <1>;
        vmmc-supply = <&vcc_io>;
                        };
 
                        vcc_sd: SWITCH_REG1 {
-                               regulator-always-on;
-                               regulator-boot-on;
                                regulator-name = "vcc_sd";
                        };
 
index 5797933..ea0a8ec 100644 (file)
                gpio = <&gpio3 11 GPIO_ACTIVE_LOW>;
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <3300000>;
-               regulator-always-on;
-               regulator-boot-on;
                vin-supply = <&vcc_io>;
        };
 
        bus-width = <8>;
        cap-mmc-highspeed;
        disable-wp;
-       keep-power-in-suspend;
        mmc-pwrseq = <&emmc_pwrseq>;
        mmc-hs200-1_2v;
        mmc-hs200-1_8v;
        clock-freq-min-max = <400000 50000000>;
        cap-sd-highspeed;
        card-detect-delay = <200>;
-       keep-power-in-suspend;
        num-slots = <1>;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
index 08fd7cf..56a1b2e 100644 (file)
                        reg = <0x59801000 0x400>;
                };
 
-               mioctrl@59810000 {
-                       compatible = "socionext,uniphier-mioctrl",
+               sdctrl@59810000 {
+                       compatible = "socionext,uniphier-ld20-sdctrl",
                                     "simple-mfd", "syscon";
                        reg = <0x59810000 0x800>;
 
-                       mio_clk: clock {
-                               compatible = "socionext,uniphier-ld20-mio-clock";
+                       sd_clk: clock {
+                               compatible = "socionext,uniphier-ld20-sd-clock";
                                #clock-cells = <1>;
                        };
 
-                       mio_rst: reset {
-                               compatible = "socionext,uniphier-ld20-mio-reset";
+                       sd_rst: reset {
+                               compatible = "socionext,uniphier-ld20-sd-reset";
                                #reset-cells = <1>;
                        };
                };
index 758d74f..a27c324 100644 (file)
@@ -94,7 +94,7 @@ struct arm64_cpu_capabilities {
        u16 capability;
        int def_scope;                  /* default scope */
        bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
-       void (*enable)(void *);         /* Called on all active CPUs */
+       int (*enable)(void *);          /* Called on all active CPUs */
        union {
                struct {        /* To be used for erratum handling only */
                        u32 midr_model;
index db0563c..f7865dd 100644 (file)
@@ -18,6 +18,9 @@
 #ifndef __ASM_EXEC_H
 #define __ASM_EXEC_H
 
+#include <linux/sched.h>
+
 extern unsigned long arch_align_stack(unsigned long sp);
+void uao_thread_switch(struct task_struct *next);
 
 #endif /* __ASM_EXEC_H */
index fd9d5fd..f5ea0ba 100644 (file)
@@ -178,11 +178,6 @@ static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
 }
 
-static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
-{
-       return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR);
-}
-
 static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE);
@@ -203,6 +198,12 @@ static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
 }
 
+static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
+{
+       return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) ||
+               kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
+}
+
 static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
index ba62df8..b71086d 100644 (file)
@@ -217,7 +217,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(kaddr)  (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
+#define __page_to_voff(page)   (((u64)(page) & ~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 e12af67..06ff7fd 100644 (file)
@@ -17,6 +17,7 @@
 #define __ASM_MODULE_H
 
 #include <asm-generic/module.h>
+#include <asm/memory.h>
 
 #define MODULE_ARCH_VERMAGIC   "aarch64"
 
@@ -32,6 +33,10 @@ u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela,
                          Elf64_Sym *sym);
 
 #ifdef CONFIG_RANDOMIZE_BASE
+#ifdef CONFIG_MODVERSIONS
+#define ARCH_RELOCATES_KCRCTAB
+#define reloc_start            (kimage_vaddr - KIMAGE_VADDR)
+#endif
 extern u64 module_alloc_base;
 #else
 #define module_alloc_base      ((u64)_etext - MODULES_VSIZE)
index 2fee2f5..5394c84 100644 (file)
@@ -44,48 +44,44 @@ static inline unsigned long __percpu_##op(void *ptr,                        \
                                                                        \
        switch (size) {                                                 \
        case 1:                                                         \
-               do {                                                    \
-                       asm ("//__per_cpu_" #op "_1\n"                  \
-                       "ldxrb    %w[ret], %[ptr]\n"                    \
+               asm ("//__per_cpu_" #op "_1\n"                          \
+               "1:     ldxrb     %w[ret], %[ptr]\n"                    \
                        #asm_op " %w[ret], %w[ret], %w[val]\n"          \
-                       "stxrb    %w[loop], %w[ret], %[ptr]\n"          \
-                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
-                         [ptr] "+Q"(*(u8 *)ptr)                        \
-                       : [val] "Ir" (val));                            \
-               } while (loop);                                         \
+               "       stxrb     %w[loop], %w[ret], %[ptr]\n"          \
+               "       cbnz      %w[loop], 1b"                         \
+               : [loop] "=&r" (loop), [ret] "=&r" (ret),               \
+                 [ptr] "+Q"(*(u8 *)ptr)                                \
+               : [val] "Ir" (val));                                    \
                break;                                                  \
        case 2:                                                         \
-               do {                                                    \
-                       asm ("//__per_cpu_" #op "_2\n"                  \
-                       "ldxrh    %w[ret], %[ptr]\n"                    \
+               asm ("//__per_cpu_" #op "_2\n"                          \
+               "1:     ldxrh     %w[ret], %[ptr]\n"                    \
                        #asm_op " %w[ret], %w[ret], %w[val]\n"          \
-                       "stxrh    %w[loop], %w[ret], %[ptr]\n"          \
-                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
-                         [ptr]  "+Q"(*(u16 *)ptr)                      \
-                       : [val] "Ir" (val));                            \
-               } while (loop);                                         \
+               "       stxrh     %w[loop], %w[ret], %[ptr]\n"          \
+               "       cbnz      %w[loop], 1b"                         \
+               : [loop] "=&r" (loop), [ret] "=&r" (ret),               \
+                 [ptr]  "+Q"(*(u16 *)ptr)                              \
+               : [val] "Ir" (val));                                    \
                break;                                                  \
        case 4:                                                         \
-               do {                                                    \
-                       asm ("//__per_cpu_" #op "_4\n"                  \
-                       "ldxr     %w[ret], %[ptr]\n"                    \
+               asm ("//__per_cpu_" #op "_4\n"                          \
+               "1:     ldxr      %w[ret], %[ptr]\n"                    \
                        #asm_op " %w[ret], %w[ret], %w[val]\n"          \
-                       "stxr     %w[loop], %w[ret], %[ptr]\n"          \
-                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
-                         [ptr] "+Q"(*(u32 *)ptr)                       \
-                       : [val] "Ir" (val));                            \
-               } while (loop);                                         \
+               "       stxr      %w[loop], %w[ret], %[ptr]\n"          \
+               "       cbnz      %w[loop], 1b"                         \
+               : [loop] "=&r" (loop), [ret] "=&r" (ret),               \
+                 [ptr] "+Q"(*(u32 *)ptr)                               \
+               : [val] "Ir" (val));                                    \
                break;                                                  \
        case 8:                                                         \
-               do {                                                    \
-                       asm ("//__per_cpu_" #op "_8\n"                  \
-                       "ldxr     %[ret], %[ptr]\n"                     \
+               asm ("//__per_cpu_" #op "_8\n"                          \
+               "1:     ldxr      %[ret], %[ptr]\n"                     \
                        #asm_op " %[ret], %[ret], %[val]\n"             \
-                       "stxr     %w[loop], %[ret], %[ptr]\n"           \
-                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
-                         [ptr] "+Q"(*(u64 *)ptr)                       \
-                       : [val] "Ir" (val));                            \
-               } while (loop);                                         \
+               "       stxr      %w[loop], %[ret], %[ptr]\n"           \
+               "       cbnz      %w[loop], 1b"                         \
+               : [loop] "=&r" (loop), [ret] "=&r" (ret),               \
+                 [ptr] "+Q"(*(u64 *)ptr)                               \
+               : [val] "Ir" (val));                                    \
                break;                                                  \
        default:                                                        \
                BUILD_BUG();                                            \
@@ -150,44 +146,40 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
 
        switch (size) {
        case 1:
-               do {
-                       asm ("//__percpu_xchg_1\n"
-                       "ldxrb %w[ret], %[ptr]\n"
-                       "stxrb %w[loop], %w[val], %[ptr]\n"
-                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
-                         [ptr] "+Q"(*(u8 *)ptr)
-                       : [val] "r" (val));
-               } while (loop);
+               asm ("//__percpu_xchg_1\n"
+               "1:     ldxrb   %w[ret], %[ptr]\n"
+               "       stxrb   %w[loop], %w[val], %[ptr]\n"
+               "       cbnz    %w[loop], 1b"
+               : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                 [ptr] "+Q"(*(u8 *)ptr)
+               : [val] "r" (val));
                break;
        case 2:
-               do {
-                       asm ("//__percpu_xchg_2\n"
-                       "ldxrh %w[ret], %[ptr]\n"
-                       "stxrh %w[loop], %w[val], %[ptr]\n"
-                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
-                         [ptr] "+Q"(*(u16 *)ptr)
-                       : [val] "r" (val));
-               } while (loop);
+               asm ("//__percpu_xchg_2\n"
+               "1:     ldxrh   %w[ret], %[ptr]\n"
+               "       stxrh   %w[loop], %w[val], %[ptr]\n"
+               "       cbnz    %w[loop], 1b"
+               : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                 [ptr] "+Q"(*(u16 *)ptr)
+               : [val] "r" (val));
                break;
        case 4:
-               do {
-                       asm ("//__percpu_xchg_4\n"
-                       "ldxr %w[ret], %[ptr]\n"
-                       "stxr %w[loop], %w[val], %[ptr]\n"
-                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
-                         [ptr] "+Q"(*(u32 *)ptr)
-                       : [val] "r" (val));
-               } while (loop);
+               asm ("//__percpu_xchg_4\n"
+               "1:     ldxr    %w[ret], %[ptr]\n"
+               "       stxr    %w[loop], %w[val], %[ptr]\n"
+               "       cbnz    %w[loop], 1b"
+               : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                 [ptr] "+Q"(*(u32 *)ptr)
+               : [val] "r" (val));
                break;
        case 8:
-               do {
-                       asm ("//__percpu_xchg_8\n"
-                       "ldxr %[ret], %[ptr]\n"
-                       "stxr %w[loop], %[val], %[ptr]\n"
-                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
-                         [ptr] "+Q"(*(u64 *)ptr)
-                       : [val] "r" (val));
-               } while (loop);
+               asm ("//__percpu_xchg_8\n"
+               "1:     ldxr    %[ret], %[ptr]\n"
+               "       stxr    %w[loop], %[val], %[ptr]\n"
+               "       cbnz    %w[loop], 1b"
+               : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                 [ptr] "+Q"(*(u64 *)ptr)
+               : [val] "r" (val));
                break;
        default:
                BUILD_BUG();
index df2e53d..60e3482 100644 (file)
@@ -188,8 +188,8 @@ static inline void spin_lock_prefetch(const void *ptr)
 
 #endif
 
-void cpu_enable_pan(void *__unused);
-void cpu_enable_uao(void *__unused);
-void cpu_enable_cache_maint_trap(void *__unused);
+int cpu_enable_pan(void *__unused);
+int cpu_enable_uao(void *__unused);
+int cpu_enable_cache_maint_trap(void *__unused);
 
 #endif /* __ASM_PROCESSOR_H */
index e8d46e8..6c80b36 100644 (file)
@@ -286,7 +286,7 @@ asm(
 
 #define write_sysreg_s(v, r) do {                                      \
        u64 __val = (u64)v;                                             \
-       asm volatile("msr_s " __stringify(r) ", %0" : : "rZ" (__val));  \
+       asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \
 } while (0)
 
 static inline void config_sctlr_el1(u32 clear, u32 set)
index bcaf6fb..55d0adb 100644 (file)
@@ -21,6 +21,7 @@
 /*
  * User space memory access functions
  */
+#include <linux/bitops.h>
 #include <linux/kasan-checks.h>
 #include <linux/string.h>
 #include <linux/thread_info.h>
@@ -102,6 +103,13 @@ static inline void set_fs(mm_segment_t fs)
        flag;                                                           \
 })
 
+/*
+ * When dealing with data aborts or instruction traps we may end up with
+ * a tagged userland pointer. Clear the tag to get a sane pointer to pass
+ * on to access_ok(), for instance.
+ */
+#define untagged_addr(addr)            sign_extend64(addr, 55)
+
 #define access_ok(type, addr, size)    __range_ok(addr, size)
 #define user_addr_max                  get_fs
 
index 42ffdb5..b0988bb 100644 (file)
@@ -280,35 +280,43 @@ static void __init register_insn_emulation_sysctl(struct ctl_table *table)
 /*
  * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
  */
-#define __user_swpX_asm(data, addr, res, temp, B)              \
+
+/* Arbitrary constant to ensure forward-progress of the LL/SC loop */
+#define __SWP_LL_SC_LOOPS      4
+
+#define __user_swpX_asm(data, addr, res, temp, temp2, B)       \
        __asm__ __volatile__(                                   \
+       "       mov             %w3, %w7\n"                     \
        ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,    \
                    CONFIG_ARM64_PAN)                           \
-       "0:     ldxr"B"         %w2, [%3]\n"                    \
-       "1:     stxr"B"         %w0, %w1, [%3]\n"               \
+       "0:     ldxr"B"         %w2, [%4]\n"                    \
+       "1:     stxr"B"         %w0, %w1, [%4]\n"               \
        "       cbz             %w0, 2f\n"                      \
-       "       mov             %w0, %w4\n"                     \
+       "       sub             %w3, %w3, #1\n"                 \
+       "       cbnz            %w3, 0b\n"                      \
+       "       mov             %w0, %w5\n"                     \
        "       b               3f\n"                           \
        "2:\n"                                                  \
        "       mov             %w1, %w2\n"                     \
        "3:\n"                                                  \
        "       .pushsection     .fixup,\"ax\"\n"               \
        "       .align          2\n"                            \
-       "4:     mov             %w0, %w5\n"                     \
+       "4:     mov             %w0, %w6\n"                     \
        "       b               3b\n"                           \
        "       .popsection"                                    \
        _ASM_EXTABLE(0b, 4b)                                    \
        _ASM_EXTABLE(1b, 4b)                                    \
        ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,    \
                CONFIG_ARM64_PAN)                               \
-       : "=&r" (res), "+r" (data), "=&r" (temp)                \
-       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)              \
+       : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \
+       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT),             \
+         "i" (__SWP_LL_SC_LOOPS)                               \
        : "memory")
 
-#define __user_swp_asm(data, addr, res, temp) \
-       __user_swpX_asm(data, addr, res, temp, "")
-#define __user_swpb_asm(data, addr, res, temp) \
-       __user_swpX_asm(data, addr, res, temp, "b")
+#define __user_swp_asm(data, addr, res, temp, temp2) \
+       __user_swpX_asm(data, addr, res, temp, temp2, "")
+#define __user_swpb_asm(data, addr, res, temp, temp2) \
+       __user_swpX_asm(data, addr, res, temp, temp2, "b")
 
 /*
  * Bit 22 of the instruction encoding distinguishes between
@@ -328,12 +336,12 @@ static int emulate_swpX(unsigned int address, unsigned int *data,
        }
 
        while (1) {
-               unsigned long temp;
+               unsigned long temp, temp2;
 
                if (type == TYPE_SWPB)
-                       __user_swpb_asm(*data, address, res, temp);
+                       __user_swpb_asm(*data, address, res, temp, temp2);
                else
-                       __user_swp_asm(*data, address, res, temp);
+                       __user_swp_asm(*data, address, res, temp, temp2);
 
                if (likely(res != -EAGAIN) || signal_pending(current))
                        break;
index 0150394..b75e917 100644 (file)
@@ -39,10 +39,11 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry,
                (arm64_ftr_reg_ctrel0.sys_val & arm64_ftr_reg_ctrel0.strict_mask);
 }
 
-static void cpu_enable_trap_ctr_access(void *__unused)
+static int cpu_enable_trap_ctr_access(void *__unused)
 {
        /* Clear SCTLR_EL1.UCT */
        config_sctlr_el1(SCTLR_EL1_UCT, 0);
+       return 0;
 }
 
 #define MIDR_RANGE(model, min, max) \
index d577f26..c02504e 100644 (file)
@@ -19,7 +19,9 @@
 #define pr_fmt(fmt) "CPU features: " fmt
 
 #include <linux/bsearch.h>
+#include <linux/cpumask.h>
 #include <linux/sort.h>
+#include <linux/stop_machine.h>
 #include <linux/types.h>
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
@@ -941,7 +943,13 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
        for (; caps->matches; caps++)
                if (caps->enable && cpus_have_cap(caps->capability))
-                       on_each_cpu(caps->enable, NULL, true);
+                       /*
+                        * Use stop_machine() as it schedules the work allowing
+                        * us to modify PSTATE, instead of on_each_cpu() which
+                        * uses an IPI, giving us a PSTATE that disappears when
+                        * we return.
+                        */
+                       stop_machine(caps->enable, NULL, cpu_online_mask);
 }
 
 /*
index 427f6d3..332e331 100644 (file)
@@ -586,8 +586,9 @@ CPU_LE(     movk    x0, #0x30d0, lsl #16    )       // Clear EE and E0E on LE systems
        b.lt    4f                              // Skip if no PMU present
        mrs     x0, pmcr_el0                    // Disable debug access traps
        ubfx    x0, x0, #11, #5                 // to EL2 and allow access to
-       msr     mdcr_el2, x0                    // all PMU counters from EL1
 4:
+       csel    x0, xzr, x0, lt                 // all PMU counters from EL1
+       msr     mdcr_el2, x0                    // (if they exist)
 
        /* Stage-2 translation */
        msr     vttbr_el2, xzr
index 27b2f13..01753cd 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/alternative.h>
 #include <asm/compat.h>
 #include <asm/cacheflush.h>
+#include <asm/exec.h>
 #include <asm/fpsimd.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
@@ -186,10 +187,19 @@ void __show_regs(struct pt_regs *regs)
        printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
               regs->pc, lr, regs->pstate);
        printk("sp : %016llx\n", sp);
-       for (i = top_reg; i >= 0; i--) {
+
+       i = top_reg;
+
+       while (i >= 0) {
                printk("x%-2d: %016llx ", i, regs->regs[i]);
-               if (i % 2 == 0)
-                       printk("\n");
+               i--;
+
+               if (i % 2 == 0) {
+                       pr_cont("x%-2d: %016llx ", i, regs->regs[i]);
+                       i--;
+               }
+
+               pr_cont("\n");
        }
        printk("\n");
 }
@@ -301,7 +311,7 @@ static void tls_thread_switch(struct task_struct *next)
 }
 
 /* Restore the UAO state depending on next's addr_limit */
-static void uao_thread_switch(struct task_struct *next)
+void uao_thread_switch(struct task_struct *next)
 {
        if (IS_ENABLED(CONFIG_ARM64_UAO)) {
                if (task_thread_info(next)->addr_limit == KERNEL_DS)
index b8799e7..1bec41b 100644 (file)
@@ -135,7 +135,7 @@ ENTRY(_cpu_resume)
 
 #ifdef CONFIG_KASAN
        mov     x0, sp
-       bl      kasan_unpoison_remaining_stack
+       bl      kasan_unpoison_task_stack_below
 #endif
 
        ldp     x19, x20, [x29, #16]
index d3f151c..8507703 100644 (file)
@@ -544,6 +544,7 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
                        return;
                }
                bootcpu_valid = true;
+               early_map_cpu_to_node(0, acpi_numa_get_nid(0, hwid));
                return;
        }
 
index ad73414..bb0cd78 100644 (file)
@@ -1,8 +1,11 @@
 #include <linux/ftrace.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <asm/alternative.h>
 #include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
+#include <asm/exec.h>
 #include <asm/pgtable.h>
 #include <asm/memory.h>
 #include <asm/mmu_context.h>
@@ -49,6 +52,14 @@ void notrace __cpu_suspend_exit(void)
         */
        set_my_cpu_offset(per_cpu_offset(cpu));
 
+       /*
+        * PSTATE was not saved over suspend/resume, re-enable any detected
+        * features that might not have been set correctly.
+        */
+       asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
+                       CONFIG_ARM64_PAN));
+       uao_thread_switch(current);
+
        /*
         * Restore HW breakpoint registers to sane values
         * before debug exceptions are possibly reenabled
index 5ff020f..c9986b3 100644 (file)
@@ -428,24 +428,28 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
        force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
-void cpu_enable_cache_maint_trap(void *__unused)
+int cpu_enable_cache_maint_trap(void *__unused)
 {
        config_sctlr_el1(SCTLR_EL1_UCI, 0);
+       return 0;
 }
 
 #define __user_cache_maint(insn, address, res)                 \
-       asm volatile (                                          \
-               "1:     " insn ", %1\n"                         \
-               "       mov     %w0, #0\n"                      \
-               "2:\n"                                          \
-               "       .pushsection .fixup,\"ax\"\n"           \
-               "       .align  2\n"                            \
-               "3:     mov     %w0, %w2\n"                     \
-               "       b       2b\n"                           \
-               "       .popsection\n"                          \
-               _ASM_EXTABLE(1b, 3b)                            \
-               : "=r" (res)                                    \
-               : "r" (address), "i" (-EFAULT) )
+       if (untagged_addr(address) >= user_addr_max())          \
+               res = -EFAULT;                                  \
+       else                                                    \
+               asm volatile (                                  \
+                       "1:     " insn ", %1\n"                 \
+                       "       mov     %w0, #0\n"              \
+                       "2:\n"                                  \
+                       "       .pushsection .fixup,\"ax\"\n"   \
+                       "       .align  2\n"                    \
+                       "3:     mov     %w0, %w2\n"             \
+                       "       b       2b\n"                   \
+                       "       .popsection\n"                  \
+                       _ASM_EXTABLE(1b, 3b)                    \
+                       : "=r" (res)                            \
+                       : "r" (address), "i" (-EFAULT) )
 
 static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 {
index 53d9159..0f87883 100644 (file)
@@ -29,7 +29,9 @@
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
+#include <linux/preempt.h>
 
+#include <asm/bug.h>
 #include <asm/cpufeature.h>
 #include <asm/exception.h>
 #include <asm/debug-monitors.h>
@@ -670,9 +672,17 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 NOKPROBE_SYMBOL(do_debug_exception);
 
 #ifdef CONFIG_ARM64_PAN
-void cpu_enable_pan(void *__unused)
+int cpu_enable_pan(void *__unused)
 {
+       /*
+        * We modify PSTATE. This won't work from irq context as the PSTATE
+        * is discarded once we return from the exception.
+        */
+       WARN_ON_ONCE(in_interrupt());
+
        config_sctlr_el1(SCTLR_EL1_SPAN, 0);
+       asm(SET_PSTATE_PAN(1));
+       return 0;
 }
 #endif /* CONFIG_ARM64_PAN */
 
@@ -683,8 +693,9 @@ void cpu_enable_pan(void *__unused)
  * We need to enable the feature at runtime (instead of adding it to
  * PSR_MODE_EL1h) as the feature may not be implemented by the cpu.
  */
-void cpu_enable_uao(void *__unused)
+int cpu_enable_uao(void *__unused)
 {
        asm(SET_PSTATE_UAO(1));
+       return 0;
 }
 #endif /* CONFIG_ARM64_UAO */
index 21c489b..212c4d1 100644 (file)
@@ -421,35 +421,35 @@ void __init mem_init(void)
 
        pr_notice("Virtual kernel memory layout:\n");
 #ifdef CONFIG_KASAN
-       pr_cont("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+       pr_notice("    kasan   : 0x%16lx - 0x%16lx   (%6ld GB)\n",
                MLG(KASAN_SHADOW_START, KASAN_SHADOW_END));
 #endif
-       pr_cont("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+       pr_notice("    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n",
                MLM(MODULES_VADDR, MODULES_END));
-       pr_cont("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
+       pr_notice("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
                MLG(VMALLOC_START, VMALLOC_END));
-       pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+       pr_notice("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
                MLK_ROUNDUP(_text, _etext));
-       pr_cont("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+       pr_notice("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
                MLK_ROUNDUP(__start_rodata, __init_begin));
-       pr_cont("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+       pr_notice("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
                MLK_ROUNDUP(__init_begin, __init_end));
-       pr_cont("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+       pr_notice("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
                MLK_ROUNDUP(_sdata, _edata));
-       pr_cont("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+       pr_notice("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
                MLK_ROUNDUP(__bss_start, __bss_stop));
-       pr_cont("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
+       pr_notice("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
                MLK(FIXADDR_START, FIXADDR_TOP));
-       pr_cont("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+       pr_notice("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
                MLM(PCI_IO_START, PCI_IO_END));
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-       pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
+       pr_notice("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
                MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
-       pr_cont("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
+       pr_notice("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
                MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
                    (unsigned long)virt_to_page(high_memory)));
 #endif
-       pr_cont("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
+       pr_notice("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
                MLM(__phys_to_virt(memblock_start_of_DRAM()),
                    (unsigned long)high_memory));
 
index 778a985..4b32168 100644 (file)
@@ -147,7 +147,7 @@ static int __init early_cpu_to_node(int cpu)
 
 static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
 {
-       return node_distance(from, to);
+       return node_distance(early_cpu_to_node(from), early_cpu_to_node(to));
 }
 
 static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
@@ -223,8 +223,11 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
        void *nd;
        int tnid;
 
-       pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
-               nid, start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
+       if (start_pfn < end_pfn)
+               pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n", nid,
+                       start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
+       else
+               pr_info("Initmem setup node %d [<memory-less node>]\n", nid);
 
        nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
        nd = __va(nd_pa);
index 8b8fe67..8d79286 100644 (file)
@@ -271,7 +271,7 @@ long arch_ptrace(struct task_struct *child, long request,
                        case BFIN_MEM_ACCESS_CORE:
                        case BFIN_MEM_ACCESS_CORE_ONLY:
                                copied = access_process_vm(child, addr, &tmp,
-                                                          to_copy, 0);
+                                                          to_copy, FOLL_FORCE);
                                if (copied)
                                        break;
 
@@ -324,7 +324,8 @@ long arch_ptrace(struct task_struct *child, long request,
                        case BFIN_MEM_ACCESS_CORE:
                        case BFIN_MEM_ACCESS_CORE_ONLY:
                                copied = access_process_vm(child, addr, &data,
-                                                          to_copy, 1);
+                                                          to_copy,
+                                                          FOLL_FORCE | FOLL_WRITE);
                                break;
                        case BFIN_MEM_ACCESS_DMA:
                                if (safe_dma_memcpy(paddr, &data, to_copy))
index b5698c8..0068fd4 100644 (file)
@@ -2722,7 +2722,6 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
        err = get_user_pages((unsigned long int)(oper.indata + prev_ix),
                             noinpages,
                             0,  /* read access only for in data */
-                            0, /* no force */
                             inpages,
                             NULL);
 
@@ -2736,8 +2735,7 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
        if (oper.do_cipher){
                err = get_user_pages((unsigned long int)oper.cipher_outdata,
                                     nooutpages,
-                                    1, /* write access for out data */
-                                    0, /* no force */
+                                    FOLL_WRITE, /* write access for out data */
                                     outpages,
                                     NULL);
                up_read(&current->mm->mmap_sem);
@@ -3151,7 +3149,7 @@ static void print_dma_descriptors(struct cryptocop_int_operation *iop)
        printk("print_dma_descriptors start\n");
 
        printk("iop:\n");
-       printk("\tsid: 0x%lld\n", iop->sid);
+       printk("\tsid: 0x%llx\n", iop->sid);
 
        printk("\tcdesc_out: 0x%p\n", iop->cdesc_out);
        printk("\tcdesc_in: 0x%p\n", iop->cdesc_in);
index f085229..f0df654 100644 (file)
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *child, long request,
                                /* The trampoline page is globally mapped, no page table to traverse.*/
                                tmp = *(unsigned long*)addr;
                        } else {
-                               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+                               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
 
                                if (copied != sizeof(tmp))
                                        break;
@@ -279,7 +279,7 @@ static int insn_size(struct task_struct *child, unsigned long pc)
   int opsize = 0;
 
   /* Read the opcode at pc (do what PTRACE_PEEKTEXT would do). */
-  copied = access_process_vm(child, pc, &opcode, sizeof(opcode), 0);
+  copied = access_process_vm(child, pc, &opcode, sizeof(opcode), FOLL_FORCE);
   if (copied != sizeof(opcode))
     return 0;
 
index b408fe6..3cef068 100644 (file)
@@ -31,7 +31,6 @@ struct thread_info {
        int                cpu;                 /* cpu we're on */
        int                preempt_count;       /* 0 => preemptable, <0 => BUG */
        mm_segment_t            addr_limit;
-       struct restart_block restart_block;
 };
 
 /*
@@ -44,9 +43,6 @@ struct thread_info {
        .cpu =          0,                      \
        .preempt_count = INIT_PREEMPT_COUNT,    \
        .addr_limit     = KERNEL_DS,            \
-       .restart_block  = {                     \
-               .fn = do_no_restart_syscall,    \
-       },                                      \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
index ad1f81f..7138303 100644 (file)
@@ -79,7 +79,7 @@ restore_sigcontext(struct sigcontext *usc, int *pd0)
        unsigned int er0;
 
        /* Always make any pending restarted system calls return -EINTR */
-       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+       current->restart_block.fn = do_no_restart_syscall;
 
        /* restore passed registers */
 #define COPY(r)  do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
index 09f8457..5ed0ea9 100644 (file)
@@ -142,7 +142,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr,
        u64 virt_addr=simple_strtoull(buf, NULL, 16);
        int ret;
 
-       ret = get_user_pages(virt_addr, 1, VM_READ, 0, NULL, NULL);
+       ret = get_user_pages(virt_addr, 1, FOLL_WRITE, NULL, NULL);
        if (ret<=0) {
 #ifdef ERR_INJ_DEBUG
                printk("Virtual address %lx is not existing.\n",virt_addr);
index 6f54d51..31aa8c0 100644 (file)
@@ -453,7 +453,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
                        return 0;
                }
        }
-       copied = access_process_vm(child, addr, &ret, sizeof(ret), 0);
+       copied = access_process_vm(child, addr, &ret, sizeof(ret), FOLL_FORCE);
        if (copied != sizeof(ret))
                return -EIO;
        *val = ret;
@@ -489,7 +489,8 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
                                *ia64_rse_skip_regs(krbs, regnum) = val;
                        }
                }
-       } else if (access_process_vm(child, addr, &val, sizeof(val), 1)
+       } else if (access_process_vm(child, addr, &val, sizeof(val),
+                               FOLL_FORCE | FOLL_WRITE)
                   != sizeof(val))
                return -EIO;
        return 0;
@@ -543,7 +544,8 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
                ret = ia64_peek(child, sw, user_rbs_end, addr, &val);
                if (ret < 0)
                        return ret;
-               if (access_process_vm(child, addr, &val, sizeof(val), 1)
+               if (access_process_vm(child, addr, &val, sizeof(val),
+                               FOLL_FORCE | FOLL_WRITE)
                    != sizeof(val))
                        return -EIO;
        }
@@ -559,7 +561,8 @@ ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
 
        /* now copy word for word from user rbs to kernel rbs: */
        for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
-               if (access_process_vm(child, addr, &val, sizeof(val), 0)
+               if (access_process_vm(child, addr, &val, sizeof(val),
+                               FOLL_FORCE)
                                != sizeof(val))
                        return -EIO;
 
@@ -1156,7 +1159,8 @@ arch_ptrace (struct task_struct *child, long request,
        case PTRACE_PEEKTEXT:
        case PTRACE_PEEKDATA:
                /* read word at location addr */
-               if (access_process_vm(child, addr, &data, sizeof(data), 0)
+               if (access_process_vm(child, addr, &data, sizeof(data),
+                               FOLL_FORCE)
                    != sizeof(data))
                        return -EIO;
                /* ensure return value is not mistaken for error code */
index 51f5e9a..c145605 100644 (file)
@@ -493,7 +493,8 @@ unregister_all_debug_traps(struct task_struct *child)
        int i;
 
        for (i = 0; i < p->nr_trap; i++)
-               access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1);
+               access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]),
+                               FOLL_FORCE | FOLL_WRITE);
        p->nr_trap = 0;
 }
 
@@ -537,7 +538,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
        unsigned long next_insn, code;
        unsigned long addr = next_pc & ~3;
 
-       if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0)
+       if (access_process_vm(child, addr, &next_insn, sizeof(next_insn),
+                       FOLL_FORCE)
            != sizeof(next_insn)) {
                return -1; /* error */
        }
@@ -546,7 +548,8 @@ embed_debug_trap(struct task_struct *child, unsigned long next_pc)
        if (register_debug_trap(child, next_pc, next_insn, &code)) {
                return -1; /* error */
        }
-       if (access_process_vm(child, addr, &code, sizeof(code), 1)
+       if (access_process_vm(child, addr, &code, sizeof(code),
+                       FOLL_FORCE | FOLL_WRITE)
            != sizeof(code)) {
                return -1; /* error */
        }
@@ -562,7 +565,8 @@ withdraw_debug_trap(struct pt_regs *regs)
        addr = (regs->bpc - 2) & ~3;
        regs->bpc -= 2;
        if (unregister_debug_trap(current, addr, &code)) {
-           access_process_vm(current, addr, &code, sizeof(code), 1);
+           access_process_vm(current, addr, &code, sizeof(code),
+                   FOLL_FORCE | FOLL_WRITE);
            invalidate_cache();
        }
 }
@@ -589,7 +593,8 @@ void user_enable_single_step(struct task_struct *child)
        /* Compute next pc.  */
        pc = get_stack_long(child, PT_BPC);
 
-       if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
+       if (access_process_vm(child, pc&~3, &insn, sizeof(insn),
+                       FOLL_FORCE)
            != sizeof(insn))
                return;
 
index 283b5a1..7e71a4e 100644 (file)
@@ -70,7 +70,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
 
                copied = access_process_vm(child, (u64)addrOthers, &tmp,
-                               sizeof(tmp), 0);
+                               sizeof(tmp), FOLL_FORCE);
                if (copied != sizeof(tmp))
                        break;
                ret = put_user(tmp, (u32 __user *) (unsigned long) data);
@@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
                ret = 0;
                if (access_process_vm(child, (u64)addrOthers, &data,
-                                       sizeof(data), 1) == sizeof(data))
+                                       sizeof(data),
+                                       FOLL_FORCE | FOLL_WRITE) == sizeof(data))
                        break;
                ret = -EIO;
                break;
index ce96149..622037d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/kdebug.h>
 #include <linux/module.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <linux/bootmem.h>
index 42d124f..d8c3c15 100644 (file)
@@ -287,7 +287,7 @@ slow_irqon:
        pages += nr;
 
        ret = get_user_pages_unlocked(start, (end - start) >> PAGE_SHIFT,
-                                     write, 0, pages);
+                                     pages, write ? FOLL_WRITE : 0);
 
        /* Have to be a bit careful with return values */
        if (nr > 0) {
index f7a184b..57d42d1 100644 (file)
@@ -32,9 +32,16 @@ static struct addr_range prep_kernel(void)
        void *addr = 0;
        struct elf_info ei;
        long len;
+       int uncompressed_image = 0;
 
-       partial_decompress(vmlinuz_addr, vmlinuz_size,
+       len = partial_decompress(vmlinuz_addr, vmlinuz_size,
                elfheader, sizeof(elfheader), 0);
+       /* assume uncompressed data if -1 is returned */
+       if (len == -1) {
+               uncompressed_image = 1;
+               memcpy(elfheader, vmlinuz_addr, sizeof(elfheader));
+               printf("No valid compressed data found, assume uncompressed data\n\r");
+       }
 
        if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
                fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
@@ -67,6 +74,13 @@ static struct addr_range prep_kernel(void)
                                        "device tree\n\r");
        }
 
+       if (uncompressed_image) {
+               memcpy(addr, vmlinuz_addr + ei.elfoffset, ei.loadsize);
+               printf("0x%lx bytes of uncompressed data copied\n\r",
+                      ei.loadsize);
+               goto out;
+       }
+
        /* Finally, decompress the kernel */
        printf("Decompressing (0x%p <- 0x%p:0x%p)...\n\r", addr,
               vmlinuz_addr, vmlinuz_addr+vmlinuz_size);
@@ -82,7 +96,7 @@ static struct addr_range prep_kernel(void)
                         len, ei.loadsize);
 
        printf("Done! Decompressed 0x%lx bytes\n\r", len);
-
+out:
        flush_cache(addr, ei.loadsize);
 
        return (struct addr_range){addr, ei.memsize};
index ee655ed..1e8fceb 100644 (file)
@@ -53,10 +53,8 @@ static inline __sum16 csum_fold(__wsum sum)
        return (__force __sum16)(~((__force u32)sum + tmp) >> 16);
 }
 
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-                                     unsigned short len,
-                                     unsigned short proto,
-                                     __wsum sum)
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len,
+                                       __u8 proto, __wsum sum)
 {
 #ifdef __powerpc64__
        unsigned long s = (__force u32)sum;
@@ -83,10 +81,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-                                       unsigned short len,
-                                       unsigned short proto,
-                                       __wsum sum)
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, __u32 len,
+                                       __u8 proto, __wsum sum)
 {
        return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
 }
index 01b8a13..3919332 100644 (file)
@@ -26,7 +26,7 @@ extern u64 pnv_first_deep_stop_state;
        std     r0,0(r1);                                       \
        ptesync;                                                \
        ld      r0,0(r1);                                       \
-1:     cmp     cr0,r0,r0;                                      \
+1:     cmpd    cr0,r0,r0;                                      \
        bne     1b;                                             \
        IDLE_INST;                                              \
        b       .
index 2e4e7d8..84d49b1 100644 (file)
        ld      reg,PACAKBASE(r13);     /* get high part of &label */   \
        ori     reg,reg,(FIXED_SYMBOL_ABS_ADDR(label))@l;
 
+#define __LOAD_HANDLER(reg, label)                                     \
+       ld      reg,PACAKBASE(r13);                                     \
+       ori     reg,reg,(ABS_ADDR(label))@l;
+
 /* Exception register prefixes */
 #define EXC_HV H
 #define EXC_STD
@@ -208,6 +212,18 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
 #define kvmppc_interrupt kvmppc_interrupt_pr
 #endif
 
+#ifdef CONFIG_RELOCATABLE
+#define BRANCH_TO_COMMON(reg, label)                                   \
+       __LOAD_HANDLER(reg, label);                                     \
+       mtctr   reg;                                                    \
+       bctr
+
+#else
+#define BRANCH_TO_COMMON(reg, label)                                   \
+       b       label
+
+#endif
+
 #define __KVM_HANDLER_PROLOG(area, n)                                  \
        BEGIN_FTR_SECTION_NESTED(947)                                   \
        ld      r10,area+EX_CFAR(r13);                                  \
index f6f68f7..99e1397 100644 (file)
@@ -52,11 +52,23 @@ static inline int mm_is_core_local(struct mm_struct *mm)
        return cpumask_subset(mm_cpumask(mm),
                              topology_sibling_cpumask(smp_processor_id()));
 }
+
+static inline int mm_is_thread_local(struct mm_struct *mm)
+{
+       return cpumask_equal(mm_cpumask(mm),
+                             cpumask_of(smp_processor_id()));
+}
+
 #else
 static inline int mm_is_core_local(struct mm_struct *mm)
 {
        return 1;
 }
+
+static inline int mm_is_thread_local(struct mm_struct *mm)
+{
+       return 1;
+}
 #endif
 
 #endif /* __KERNEL__ */
index cf12c58..e8cdfec 100644 (file)
 
 #define __NR__exit __NR_exit
 
+#define __IGNORE_pkey_mprotect
+#define __IGNORE_pkey_alloc
+#define __IGNORE_pkey_free
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
index f129408..08ba447 100644 (file)
@@ -95,19 +95,35 @@ __start_interrupts:
 /* No virt vectors corresponding with 0x0..0x100 */
 EXC_VIRT_NONE(0x4000, 0x4100)
 
-EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
-       SET_SCRATCH0(r13)
+
 #ifdef CONFIG_PPC_P7_NAP
-BEGIN_FTR_SECTION
-       /* Running native on arch 2.06 or later, check if we are
-        * waking up from nap/sleep/winkle.
+       /*
+        * If running native on arch 2.06 or later, check if we are waking up
+        * from nap/sleep/winkle, and branch to idle handler.
         */
-       mfspr   r13,SPRN_SRR1
-       rlwinm. r13,r13,47-31,30,31
-       beq     9f
+#define IDLETEST(n)                                                    \
+       BEGIN_FTR_SECTION ;                                             \
+       mfspr   r10,SPRN_SRR1 ;                                         \
+       rlwinm. r10,r10,47-31,30,31 ;                                   \
+       beq-    1f ;                                                    \
+       cmpwi   cr3,r10,2 ;                                             \
+       BRANCH_TO_COMMON(r10, system_reset_idle_common) ;               \
+1:                                                                     \
+       END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+#else
+#define IDLETEST NOTEST
+#endif
 
-       cmpwi   cr3,r13,2
-       GET_PACA(r13)
+EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
+       SET_SCRATCH0(r13)
+       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
+                                IDLETEST, 0x100)
+
+EXC_REAL_END(system_reset, 0x100, 0x200)
+EXC_VIRT_NONE(0x4100, 0x4200)
+
+#ifdef CONFIG_PPC_P7_NAP
+EXC_COMMON_BEGIN(system_reset_idle_common)
        bl      pnv_restore_hyp_resource
 
        li      r0,PNV_THREAD_RUNNING
@@ -130,14 +146,8 @@ BEGIN_FTR_SECTION
        blt     cr3,2f
        b       pnv_wakeup_loss
 2:     b       pnv_wakeup_noloss
+#endif
 
-9:
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
-#endif /* CONFIG_PPC_P7_NAP */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
-                                NOTEST, 0x100)
-EXC_REAL_END(system_reset, 0x100, 0x200)
-EXC_VIRT_NONE(0x4100, 0x4200)
 EXC_COMMON(system_reset_common, 0x100, system_reset_exception)
 
 #ifdef CONFIG_PPC_PSERIES
@@ -817,10 +827,8 @@ EXC_VIRT(trap_0b, 0x4b00, 0x4c00, 0xb00)
 TRAMP_KVM(PACA_EXGEN, 0xb00)
 EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
 
-
-#define LOAD_SYSCALL_HANDLER(reg)                              \
-       ld      reg,PACAKBASE(r13);                             \
-       ori     reg,reg,(ABS_ADDR(system_call_common))@l;
+#define LOAD_SYSCALL_HANDLER(reg)                                      \
+       __LOAD_HANDLER(reg, system_call_common)
 
 /* Syscall routine is used twice, in reloc-off and reloc-on paths */
 #define SYSCALL_PSERIES_1                                      \
index 9781c69..03d089b 100644 (file)
@@ -275,7 +275,7 @@ int hw_breakpoint_handler(struct die_args *args)
        if (!stepped) {
                WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "
                        "0x%lx will be disabled.", info->address);
-               perf_event_disable(bp);
+               perf_event_disable_inatomic(bp);
                goto out;
        }
        /*
index bd739fe..72dac0b 100644 (file)
@@ -90,6 +90,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
  * Threads will spin in HMT_LOW until the lock bit is cleared.
  * r14 - pointer to core_idle_state
  * r15 - used to load contents of core_idle_state
+ * r9  - used as a temporary variable
  */
 
 core_idle_lock_held:
@@ -99,6 +100,8 @@ core_idle_lock_held:
        bne     3b
        HMT_MEDIUM
        lwarx   r15,0,r14
+       andi.   r9,r15,PNV_CORE_IDLE_LOCK_BIT
+       bne     core_idle_lock_held
        blr
 
 /*
@@ -163,12 +166,6 @@ _GLOBAL(pnv_powersave_common)
        std     r9,_MSR(r1)
        std     r1,PACAR1(r13)
 
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
-       /* Tell KVM we're entering idle */
-       li      r4,KVM_HWTHREAD_IN_IDLE
-       stb     r4,HSTATE_HWTHREAD_STATE(r13)
-#endif
-
        /*
         * Go to real mode to do the nap, as required by the architecture.
         * Also, we need to be in real mode before setting hwthread_state,
@@ -185,6 +182,26 @@ _GLOBAL(pnv_powersave_common)
 
        .globl pnv_enter_arch207_idle_mode
 pnv_enter_arch207_idle_mode:
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+       /* Tell KVM we're entering idle */
+       li      r4,KVM_HWTHREAD_IN_IDLE
+       /******************************************************/
+       /*  N O T E   W E L L    ! ! !    N O T E   W E L L   */
+       /* The following store to HSTATE_HWTHREAD_STATE(r13)  */
+       /* MUST occur in real mode, i.e. with the MMU off,    */
+       /* and the MMU must stay off until we clear this flag */
+       /* and test HSTATE_HWTHREAD_REQ(r13) in the system    */
+       /* reset interrupt vector in exceptions-64s.S.        */
+       /* The reason is that another thread can switch the   */
+       /* MMU to a guest context whenever this flag is set   */
+       /* to KVM_HWTHREAD_IN_IDLE, and if the MMU was on,    */
+       /* that would potentially cause this thread to start  */
+       /* executing instructions from guest memory in        */
+       /* hypervisor mode, leading to a host crash or data   */
+       /* corruption, or worse.                              */
+       /******************************************************/
+       stb     r4,HSTATE_HWTHREAD_STATE(r13)
+#endif
        stb     r3,PACA_THREAD_IDLE_STATE(r13)
        cmpwi   cr3,r3,PNV_THREAD_SLEEP
        bge     cr3,2f
@@ -250,6 +267,12 @@ enter_winkle:
  * r3 - requested stop state
  */
 power_enter_stop:
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+       /* Tell KVM we're entering idle */
+       li      r4,KVM_HWTHREAD_IN_IDLE
+       /* DO THIS IN REAL MODE!  See comment above. */
+       stb     r4,HSTATE_HWTHREAD_STATE(r13)
+#endif
 /*
  * Check if the requested state is a deep idle state.
  */
index 9e7c10f..ce6dc61 100644 (file)
@@ -1012,7 +1012,7 @@ void restore_tm_state(struct pt_regs *regs)
        /* Ensure that restore_math() will restore */
        if (msr_diff & MSR_FP)
                current->thread.load_fp = 1;
-#ifdef CONFIG_ALIVEC
+#ifdef CONFIG_ALTIVEC
        if (cpu_has_feature(CPU_FTR_ALTIVEC) && msr_diff & MSR_VEC)
                current->thread.load_vec = 1;
 #endif
index f52b7db..010b7b3 100644 (file)
@@ -74,7 +74,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
 
                copied = access_process_vm(child, (u64)addrOthers, &tmp,
-                               sizeof(tmp), 0);
+                               sizeof(tmp), FOLL_FORCE);
                if (copied != sizeof(tmp))
                        break;
                ret = put_user(tmp, (u32 __user *)data);
@@ -179,7 +179,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
                ret = 0;
                if (access_process_vm(child, (u64)addrOthers, &tmp,
-                                       sizeof(tmp), 1) == sizeof(tmp))
+                                       sizeof(tmp),
+                                       FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
                        break;
                ret = -EIO;
                break;
index 82ff5de..a0ea63a 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/ppc-opcode.h>
 #include <asm/pnv-pci.h>
 #include <asm/opal.h>
+#include <asm/smp.h>
 
 #include "book3s_xics.h"
 
index bb03542..362954f 100644 (file)
@@ -106,6 +106,8 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
        switch (REGION_ID(ea)) {
        case USER_REGION_ID:
                pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
+               if (mm == NULL)
+                       return 1;
                psize = get_slice_psize(mm, ea);
                ssize = user_segment_size(ea);
                vsid = get_vsid(mm->context.id, ea, ssize);
index 75b9cd6..a51c188 100644 (file)
@@ -845,7 +845,7 @@ void __init dump_numa_cpu_topology(void)
                return;
 
        for_each_online_node(node) {
-               printk(KERN_DEBUG "Node %d CPUs:", node);
+               pr_info("Node %d CPUs:", node);
 
                count = 0;
                /*
@@ -856,52 +856,18 @@ void __init dump_numa_cpu_topology(void)
                        if (cpumask_test_cpu(cpu,
                                        node_to_cpumask_map[node])) {
                                if (count == 0)
-                                       printk(" %u", cpu);
+                                       pr_cont(" %u", cpu);
                                ++count;
                        } else {
                                if (count > 1)
-                                       printk("-%u", cpu - 1);
+                                       pr_cont("-%u", cpu - 1);
                                count = 0;
                        }
                }
 
                if (count > 1)
-                       printk("-%u", nr_cpu_ids - 1);
-               printk("\n");
-       }
-}
-
-static void __init dump_numa_memory_topology(void)
-{
-       unsigned int node;
-       unsigned int count;
-
-       if (min_common_depth == -1 || !numa_enabled)
-               return;
-
-       for_each_online_node(node) {
-               unsigned long i;
-
-               printk(KERN_DEBUG "Node %d Memory:", node);
-
-               count = 0;
-
-               for (i = 0; i < memblock_end_of_DRAM();
-                    i += (1 << SECTION_SIZE_BITS)) {
-                       if (early_pfn_to_nid(i >> PAGE_SHIFT) == node) {
-                               if (count == 0)
-                                       printk(" 0x%lx", i);
-                               ++count;
-                       } else {
-                               if (count > 0)
-                                       printk("-0x%lx", i);
-                               count = 0;
-                       }
-               }
-
-               if (count > 0)
-                       printk("-0x%lx", i);
-               printk("\n");
+                       pr_cont("-%u", nr_cpu_ids - 1);
+               pr_cont("\n");
        }
 }
 
@@ -947,8 +913,6 @@ void __init initmem_init(void)
 
        if (parse_numa_properties())
                setup_nonnuma();
-       else
-               dump_numa_memory_topology();
 
        memblock_dump_all();
 
index 0e49ec5..bda8c43 100644 (file)
@@ -175,7 +175,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
        if (unlikely(pid == MMU_NO_CONTEXT))
                goto no_context;
 
-       if (!mm_is_core_local(mm)) {
+       if (!mm_is_thread_local(mm)) {
                int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
 
                if (lock_tlbie)
@@ -201,7 +201,7 @@ void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
        if (unlikely(pid == MMU_NO_CONTEXT))
                goto no_context;
 
-       if (!mm_is_core_local(mm)) {
+       if (!mm_is_thread_local(mm)) {
                int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
 
                if (lock_tlbie)
@@ -226,7 +226,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
        pid = mm ? mm->context.id : 0;
        if (unlikely(pid == MMU_NO_CONTEXT))
                goto bail;
-       if (!mm_is_core_local(mm)) {
+       if (!mm_is_thread_local(mm)) {
                int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
 
                if (lock_tlbie)
@@ -321,7 +321,7 @@ void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
 {
        unsigned long pid;
        unsigned long addr;
-       int local = mm_is_core_local(mm);
+       int local = mm_is_thread_local(mm);
        unsigned long ap = mmu_get_ap(psize);
        int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
        unsigned long page_size = 1UL << mmu_psize_defs[psize].shift;
index 64053d9..836c562 100644 (file)
@@ -12,9 +12,7 @@
 
 #ifndef __ASSEMBLY__
 
-unsigned long return_address(int depth);
-
-#define ftrace_return_address(n) return_address(n)
+#define ftrace_return_address(n) __builtin_return_address(n)
 
 void _mcount(void);
 void ftrace_caller(void);
index 0332317..602af69 100644 (file)
@@ -192,7 +192,7 @@ struct task_struct;
 struct mm_struct;
 struct seq_file;
 
-typedef int (*dump_trace_func_t)(void *data, unsigned long address);
+typedef int (*dump_trace_func_t)(void *data, unsigned long address, int reliable);
 void dump_trace(dump_trace_func_t func, void *data,
                struct task_struct *task, unsigned long sp);
 
index 02613ba..3066031 100644 (file)
@@ -9,6 +9,9 @@
 #include <uapi/asm/unistd.h>
 
 #define __IGNORE_time
+#define __IGNORE_pkey_mprotect
+#define __IGNORE_pkey_alloc
+#define __IGNORE_pkey_free
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
index 43446fa..c74c592 100644 (file)
@@ -2014,12 +2014,12 @@ void show_code(struct pt_regs *regs)
                        *ptr++ = '\t';
                ptr += print_insn(ptr, code + start, addr);
                start += opsize;
-               printk("%s", buffer);
+               pr_cont("%s", buffer);
                ptr = buffer;
                ptr += sprintf(ptr, "\n          ");
                hops++;
        }
-       printk("\n");
+       pr_cont("\n");
 }
 
 void print_fn_code(unsigned char *code, unsigned long len)
index 6693383..55d4fe1 100644 (file)
@@ -38,10 +38,10 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
                if (sp < low || sp > high - sizeof(*sf))
                        return sp;
                sf = (struct stack_frame *) sp;
+               if (func(data, sf->gprs[8], 0))
+                       return sp;
                /* Follow the backchain. */
                while (1) {
-                       if (func(data, sf->gprs[8]))
-                               return sp;
                        low = sp;
                        sp = sf->back_chain;
                        if (!sp)
@@ -49,6 +49,8 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
                        if (sp <= low || sp > high - sizeof(*sf))
                                return sp;
                        sf = (struct stack_frame *) sp;
+                       if (func(data, sf->gprs[8], 1))
+                               return sp;
                }
                /* Zero backchain detected, check for interrupt frame. */
                sp = (unsigned long) (sf + 1);
@@ -56,7 +58,7 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
                        return sp;
                regs = (struct pt_regs *) sp;
                if (!user_mode(regs)) {
-                       if (func(data, regs->psw.addr))
+                       if (func(data, regs->psw.addr, 1))
                                return sp;
                }
                low = sp;
@@ -85,33 +87,12 @@ void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task,
 }
 EXPORT_SYMBOL_GPL(dump_trace);
 
-struct return_address_data {
-       unsigned long address;
-       int depth;
-};
-
-static int __return_address(void *data, unsigned long address)
-{
-       struct return_address_data *rd = data;
-
-       if (rd->depth--)
-               return 0;
-       rd->address = address;
-       return 1;
-}
-
-unsigned long return_address(int depth)
-{
-       struct return_address_data rd = { .depth = depth + 2 };
-
-       dump_trace(__return_address, &rd, NULL, current_stack_pointer());
-       return rd.address;
-}
-EXPORT_SYMBOL_GPL(return_address);
-
-static int show_address(void *data, unsigned long address)
+static int show_address(void *data, unsigned long address, int reliable)
 {
-       printk("([<%016lx>] %pSR)\n", address, (void *)address);
+       if (reliable)
+               printk(" [<%016lx>] %pSR \n", address, (void *)address);
+       else
+               printk("([<%016lx>] %pSR)\n", address, (void *)address);
        return 0;
 }
 
@@ -138,14 +119,14 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                else
                        stack = (unsigned long *)task->thread.ksp;
        }
+       printk(KERN_DEFAULT "Stack:\n");
        for (i = 0; i < 20; i++) {
                if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
                        break;
-               if ((i * sizeof(long) % 32) == 0)
-                       printk("%s       ", i == 0 ? "" : "\n");
-               printk("%016lx ", *stack++);
+               if (i % 4 == 0)
+                       printk(KERN_DEFAULT "       ");
+               pr_cont("%016lx%c", *stack++, i % 4 == 3 ? '\n' : ' ');
        }
-       printk("\n");
        show_trace(task, (unsigned long)sp);
 }
 
@@ -163,13 +144,13 @@ void show_registers(struct pt_regs *regs)
        mode = user_mode(regs) ? "User" : "Krnl";
        printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
        if (!user_mode(regs))
-               printk(" (%pSR)", (void *)regs->psw.addr);
-       printk("\n");
+               pr_cont(" (%pSR)", (void *)regs->psw.addr);
+       pr_cont("\n");
        printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
               "P:%x AS:%x CC:%x PM:%x", psw->r, psw->t, psw->i, psw->e,
               psw->key, psw->m, psw->w, psw->p, psw->as, psw->cc, psw->pm);
-       printk(" RI:%x EA:%x", psw->ri, psw->eaba);
-       printk("\n%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
+       pr_cont(" RI:%x EA:%x\n", psw->ri, psw->eaba);
+       printk("%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
               regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
        printk("           %016lx %016lx %016lx %016lx\n",
               regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
@@ -205,14 +186,14 @@ void die(struct pt_regs *regs, const char *str)
        printk("%s: %04x ilc:%d [#%d] ", str, regs->int_code & 0xffff,
               regs->int_code >> 17, ++die_counter);
 #ifdef CONFIG_PREEMPT
-       printk("PREEMPT ");
+       pr_cont("PREEMPT ");
 #endif
 #ifdef CONFIG_SMP
-       printk("SMP ");
+       pr_cont("SMP ");
 #endif
        if (debug_pagealloc_enabled())
-               printk("DEBUG_PAGEALLOC");
-       printk("\n");
+               pr_cont("DEBUG_PAGEALLOC");
+       pr_cont("\n");
        notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
        print_modules();
        show_regs(regs);
index 17431f6..955a7b6 100644 (file)
@@ -222,7 +222,7 @@ static int __init service_level_perf_register(void)
 }
 arch_initcall(service_level_perf_register);
 
-static int __perf_callchain_kernel(void *data, unsigned long address)
+static int __perf_callchain_kernel(void *data, unsigned long address, int reliable)
 {
        struct perf_callchain_entry_ctx *entry = data;
 
index 44f84b2..355db9d 100644 (file)
@@ -27,12 +27,12 @@ static int __save_address(void *data, unsigned long address, int nosched)
        return 1;
 }
 
-static int save_address(void *data, unsigned long address)
+static int save_address(void *data, unsigned long address, int reliable)
 {
        return __save_address(data, address, 0);
 }
 
-static int save_address_nosched(void *data, unsigned long address)
+static int save_address_nosched(void *data, unsigned long address, int reliable)
 {
        return __save_address(data, address, 1);
 }
index 1cab8a1..7a27eeb 100644 (file)
@@ -119,8 +119,13 @@ static int handle_validity(struct kvm_vcpu *vcpu)
 
        vcpu->stat.exit_validity++;
        trace_kvm_s390_intercept_validity(vcpu, viwhy);
-       WARN_ONCE(true, "kvm: unhandled validity intercept 0x%x\n", viwhy);
-       return -EOPNOTSUPP;
+       KVM_EVENT(3, "validity intercept 0x%x for pid %u (kvm 0x%pK)", viwhy,
+                 current->pid, vcpu->kvm);
+
+       /* do not warn on invalid runtime instrumentation mode */
+       WARN_ONCE(viwhy != 0x44, "kvm: unhandled validity intercept 0x%x\n",
+                 viwhy);
+       return -EINVAL;
 }
 
 static int handle_instruction(struct kvm_vcpu *vcpu)
index adb0c34..18d4107 100644 (file)
@@ -266,7 +266,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        /* Try to get the remaining pages with get_user_pages */
        start += nr << PAGE_SHIFT;
        pages += nr;
-       ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages);
+       ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
+                                     write ? FOLL_WRITE : 0);
        /* Have to be a bit careful with return values */
        if (nr > 0)
                ret = (ret < 0) ? nr : ret + nr;
index cd404aa..4a0c5bc 100644 (file)
@@ -217,6 +217,7 @@ static __init int setup_hugepagesz(char *opt)
        } else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) {
                hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
        } else {
+               hugetlb_bad_size();
                pr_err("hugepagesz= specifies an unsupported page size %s\n",
                        string);
                return 0;
index f56a39b..b3e9d18 100644 (file)
@@ -151,36 +151,40 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size, bool for_device)
 {
-       unsigned long normal_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
-       unsigned long dma_end_pfn = PFN_DOWN(MAX_DMA_ADDRESS);
+       unsigned long zone_start_pfn, zone_end_pfn, nr_pages;
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long size_pages = PFN_DOWN(size);
-       unsigned long nr_pages;
-       int rc, zone_enum;
+       pg_data_t *pgdat = NODE_DATA(nid);
+       struct zone *zone;
+       int rc, i;
 
        rc = vmem_add_mapping(start, size);
        if (rc)
                return rc;
 
-       while (size_pages > 0) {
-               if (start_pfn < dma_end_pfn) {
-                       nr_pages = (start_pfn + size_pages > dma_end_pfn) ?
-                                  dma_end_pfn - start_pfn : size_pages;
-                       zone_enum = ZONE_DMA;
-               } else if (start_pfn < normal_end_pfn) {
-                       nr_pages = (start_pfn + size_pages > normal_end_pfn) ?
-                                  normal_end_pfn - start_pfn : size_pages;
-                       zone_enum = ZONE_NORMAL;
+       for (i = 0; i < MAX_NR_ZONES; i++) {
+               zone = pgdat->node_zones + i;
+               if (zone_idx(zone) != ZONE_MOVABLE) {
+                       /* Add range within existing zone limits, if possible */
+                       zone_start_pfn = zone->zone_start_pfn;
+                       zone_end_pfn = zone->zone_start_pfn +
+                                      zone->spanned_pages;
                } else {
-                       nr_pages = size_pages;
-                       zone_enum = ZONE_MOVABLE;
+                       /* Add remaining range to ZONE_MOVABLE */
+                       zone_start_pfn = start_pfn;
+                       zone_end_pfn = start_pfn + size_pages;
                }
-               rc = __add_pages(nid, NODE_DATA(nid)->node_zones + zone_enum,
-                                start_pfn, size_pages);
+               if (start_pfn < zone_start_pfn || start_pfn >= zone_end_pfn)
+                       continue;
+               nr_pages = (start_pfn + size_pages > zone_end_pfn) ?
+                          zone_end_pfn - start_pfn : size_pages;
+               rc = __add_pages(nid, zone, start_pfn, nr_pages);
                if (rc)
                        break;
                start_pfn += nr_pages;
                size_pages -= nr_pages;
+               if (!size_pages)
+                       break;
        }
        if (rc)
                vmem_remove_mapping(start, size);
index 16f4c39..9a4de45 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <asm/processor.h>
 
-static int __s390_backtrace(void *data, unsigned long address)
+static int __s390_backtrace(void *data, unsigned long address, int reliable)
 {
        unsigned int *depth = data;
 
index 5583618..4f7314d 100644 (file)
@@ -131,7 +131,7 @@ read_tsk_long(struct task_struct *child,
 {
        int copied;
 
-       copied = access_process_vm(child, addr, res, sizeof(*res), 0);
+       copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
 
        return copied != sizeof(*res) ? -EIO : 0;
 }
@@ -142,7 +142,7 @@ read_tsk_short(struct task_struct *child,
 {
        int copied;
 
-       copied = access_process_vm(child, addr, res, sizeof(*res), 0);
+       copied = access_process_vm(child, addr, res, sizeof(*res), FOLL_FORCE);
 
        return copied != sizeof(*res) ? -EIO : 0;
 }
@@ -153,7 +153,8 @@ write_tsk_short(struct task_struct *child,
 {
        int copied;
 
-       copied = access_process_vm(child, addr, &val, sizeof(val), 1);
+       copied = access_process_vm(child, addr, &val, sizeof(val),
+                       FOLL_FORCE | FOLL_WRITE);
 
        return copied != sizeof(val) ? -EIO : 0;
 }
@@ -164,7 +165,8 @@ write_tsk_long(struct task_struct *child,
 {
        int copied;
 
-       copied = access_process_vm(child, addr, &val, sizeof(val), 1);
+       copied = access_process_vm(child, addr, &val, sizeof(val),
+                       FOLL_FORCE | FOLL_WRITE);
 
        return copied != sizeof(val) ? -EIO : 0;
 }
index 0047666..336f33a 100644 (file)
@@ -31,7 +31,7 @@ isa-y                                 := $(isa-y)-up
 endif
 
 cflags-$(CONFIG_CPU_SH2)               := $(call cc-option,-m2,)
-cflags-$(CONFIG_CPU_J2)                        := $(call cc-option,-mj2,)
+cflags-$(CONFIG_CPU_J2)                        += $(call cc-option,-mj2,)
 cflags-$(CONFIG_CPU_SH2A)              += $(call cc-option,-m2a,) \
                                           $(call cc-option,-m2a-nofpu,) \
                                           $(call cc-option,-m4-nofpu,)
index e9c2c42..4e21949 100644 (file)
@@ -22,6 +22,16 @@ config SH_DEVICE_TREE
          have sufficient driver coverage to use this option; do not
          select it if you are using original SuperH hardware.
 
+config SH_JCORE_SOC
+       bool "J-Core SoC"
+       depends on SH_DEVICE_TREE && (CPU_SH2 || CPU_J2)
+       select CLKSRC_JCORE_PIT
+       select JCORE_AIC
+       default y if CPU_J2
+       help
+         Select this option to include drivers core components of the
+         J-Core SoC, including interrupt controllers and timers.
+
 config SH_SOLUTION_ENGINE
        bool "SolutionEngine"
        select SOLUTION_ENGINE
index 94d1eca..2eb81eb 100644 (file)
@@ -8,6 +8,7 @@ CONFIG_MEMORY_START=0x10000000
 CONFIG_MEMORY_SIZE=0x04000000
 CONFIG_CPU_BIG_ENDIAN=y
 CONFIG_SH_DEVICE_TREE=y
+CONFIG_SH_JCORE_SOC=y
 CONFIG_HZ_100=y
 CONFIG_CMDLINE_OVERWRITE=y
 CONFIG_CMDLINE="console=ttyUL0 earlycon"
@@ -20,6 +21,7 @@ CONFIG_INET=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_NETDEVICES=y
+CONFIG_SERIAL_EARLYCON=y
 CONFIG_SERIAL_UARTLITE=y
 CONFIG_SERIAL_UARTLITE_CONSOLE=y
 CONFIG_I2C=y
index 40fa6c8..063c298 100644 (file)
@@ -258,7 +258,8 @@ slow_irqon:
                pages += nr;
 
                ret = get_user_pages_unlocked(start,
-                       (end - start) >> PAGE_SHIFT, write, 0, pages);
+                       (end - start) >> PAGE_SHIFT, pages,
+                       write ? FOLL_WRITE : 0);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index a6cfdab..5b0ed48 100644 (file)
@@ -24,9 +24,10 @@ typedef struct {
        unsigned int    icache_line_size;
        unsigned int    ecache_size;
        unsigned int    ecache_line_size;
-       unsigned short  sock_id;
+       unsigned short  sock_id;        /* physical package */
        unsigned short  core_id;
-       int             proc_id;
+       unsigned short  max_cache_id;   /* groupings of highest shared cache */
+       unsigned short  proc_id;        /* strand (aka HW thread) id */
 } cpuinfo_sparc;
 
 DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
index d9c5876..8011e79 100644 (file)
@@ -134,7 +134,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
        *(volatile __u32 *)&lp->lock = ~0U;
 }
 
-static void inline arch_write_unlock(arch_rwlock_t *lock)
+static inline void arch_write_unlock(arch_rwlock_t *lock)
 {
        __asm__ __volatile__(
 "      st              %%g0, [%0]"
index 87990b7..07c9f2e 100644 (file)
@@ -96,7 +96,7 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long fla
 
 /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
 
-static void inline arch_read_lock(arch_rwlock_t *lock)
+static inline void arch_read_lock(arch_rwlock_t *lock)
 {
        unsigned long tmp1, tmp2;
 
@@ -119,7 +119,7 @@ static void inline arch_read_lock(arch_rwlock_t *lock)
        : "memory");
 }
 
-static int inline arch_read_trylock(arch_rwlock_t *lock)
+static inline int arch_read_trylock(arch_rwlock_t *lock)
 {
        int tmp1, tmp2;
 
@@ -140,7 +140,7 @@ static int inline arch_read_trylock(arch_rwlock_t *lock)
        return tmp1;
 }
 
-static void inline arch_read_unlock(arch_rwlock_t *lock)
+static inline void arch_read_unlock(arch_rwlock_t *lock)
 {
        unsigned long tmp1, tmp2;
 
@@ -156,7 +156,7 @@ static void inline arch_read_unlock(arch_rwlock_t *lock)
        : "memory");
 }
 
-static void inline arch_write_lock(arch_rwlock_t *lock)
+static inline void arch_write_lock(arch_rwlock_t *lock)
 {
        unsigned long mask, tmp1, tmp2;
 
@@ -181,7 +181,7 @@ static void inline arch_write_lock(arch_rwlock_t *lock)
        : "memory");
 }
 
-static void inline arch_write_unlock(arch_rwlock_t *lock)
+static inline void arch_write_unlock(arch_rwlock_t *lock)
 {
        __asm__ __volatile__(
 "      stw             %%g0, [%0]"
@@ -190,7 +190,7 @@ static void inline arch_write_unlock(arch_rwlock_t *lock)
        : "memory");
 }
 
-static int inline arch_write_trylock(arch_rwlock_t *lock)
+static inline int arch_write_trylock(arch_rwlock_t *lock)
 {
        unsigned long mask, tmp1, tmp2, result;
 
index bec481a..7b4898a 100644 (file)
@@ -44,14 +44,20 @@ int __node_distance(int, int);
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).proc_id)
 #define topology_core_id(cpu)                  (cpu_data(cpu).core_id)
 #define topology_core_cpumask(cpu)             (&cpu_core_sib_map[cpu])
+#define topology_core_cache_cpumask(cpu)       (&cpu_core_sib_cache_map[cpu])
 #define topology_sibling_cpumask(cpu)          (&per_cpu(cpu_sibling_map, cpu))
 #endif /* CONFIG_SMP */
 
 extern cpumask_t cpu_core_map[NR_CPUS];
 extern cpumask_t cpu_core_sib_map[NR_CPUS];
+extern cpumask_t cpu_core_sib_cache_map[NR_CPUS];
+
+/**
+ * Return cores that shares the last level cache.
+ */
 static inline const struct cpumask *cpu_coregroup_mask(int cpu)
 {
-        return &cpu_core_map[cpu];
+       return &cpu_core_sib_cache_map[cpu];
 }
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
index b68acc5..5373136 100644 (file)
@@ -82,7 +82,6 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
        return 1;
 }
 
-void __ret_efault(void);
 void __retl_efault(void);
 
 /* Uh, these should become the main single-value transfer routines..
@@ -189,55 +188,34 @@ int __get_user_bad(void);
 unsigned long __must_check ___copy_from_user(void *to,
                                             const void __user *from,
                                             unsigned long size);
-unsigned long copy_from_user_fixup(void *to, const void __user *from,
-                                  unsigned long size);
 static inline unsigned long __must_check
 copy_from_user(void *to, const void __user *from, unsigned long size)
 {
-       unsigned long ret;
-
        check_object_size(to, size, false);
 
-       ret = ___copy_from_user(to, from, size);
-       if (unlikely(ret))
-               ret = copy_from_user_fixup(to, from, size);
-
-       return ret;
+       return ___copy_from_user(to, from, size);
 }
 #define __copy_from_user copy_from_user
 
 unsigned long __must_check ___copy_to_user(void __user *to,
                                           const void *from,
                                           unsigned long size);
-unsigned long copy_to_user_fixup(void __user *to, const void *from,
-                                unsigned long size);
 static inline unsigned long __must_check
 copy_to_user(void __user *to, const void *from, unsigned long size)
 {
-       unsigned long ret;
-
        check_object_size(from, size, true);
 
-       ret = ___copy_to_user(to, from, size);
-       if (unlikely(ret))
-               ret = copy_to_user_fixup(to, from, size);
-       return ret;
+       return ___copy_to_user(to, from, size);
 }
 #define __copy_to_user copy_to_user
 
 unsigned long __must_check ___copy_in_user(void __user *to,
                                           const void __user *from,
                                           unsigned long size);
-unsigned long copy_in_user_fixup(void __user *to, void __user *from,
-                                unsigned long size);
 static inline unsigned long __must_check
 copy_in_user(void __user *to, void __user *from, unsigned long size)
 {
-       unsigned long ret = ___copy_in_user(to, from, size);
-
-       if (unlikely(ret))
-               ret = copy_in_user_fixup(to, from, size);
-       return ret;
+       return ___copy_in_user(to, from, size);
 }
 #define __copy_in_user copy_in_user
 
index beba6c1..6aa3da1 100644 (file)
@@ -926,48 +926,11 @@ tlb_type: .word   0       /* Must NOT end up in BSS */
 EXPORT_SYMBOL(tlb_type)
        .section        ".fixup",#alloc,#execinstr
 
-       .globl  __ret_efault, __retl_efault, __ret_one, __retl_one
-ENTRY(__ret_efault)
-       ret
-        restore %g0, -EFAULT, %o0
-ENDPROC(__ret_efault)
-EXPORT_SYMBOL(__ret_efault)
-
 ENTRY(__retl_efault)
        retl
         mov    -EFAULT, %o0
 ENDPROC(__retl_efault)
 
-ENTRY(__retl_one)
-       retl
-        mov    1, %o0
-ENDPROC(__retl_one)
-
-ENTRY(__retl_one_fp)
-       VISExitHalf
-       retl
-        mov    1, %o0
-ENDPROC(__retl_one_fp)
-
-ENTRY(__ret_one_asi)
-       wr      %g0, ASI_AIUS, %asi
-       ret
-        restore %g0, 1, %o0
-ENDPROC(__ret_one_asi)
-
-ENTRY(__retl_one_asi)
-       wr      %g0, ASI_AIUS, %asi
-       retl
-        mov    1, %o0
-ENDPROC(__retl_one_asi)
-
-ENTRY(__retl_one_asi_fp)
-       wr      %g0, ASI_AIUS, %asi
-       VISExitHalf
-       retl
-        mov    1, %o0
-ENDPROC(__retl_one_asi_fp)
-
 ENTRY(__retl_o1)
        retl
         mov    %o1, %o0
index 59bbeff..07933b9 100644 (file)
 void arch_jump_label_transform(struct jump_entry *entry,
                               enum jump_label_type type)
 {
-       u32 val;
        u32 *insn = (u32 *) (unsigned long) entry->code;
+       u32 val;
 
        if (type == JUMP_LABEL_JMP) {
                s32 off = (s32)entry->target - (s32)entry->code;
+               bool use_v9_branch = false;
+
+               BUG_ON(off & 3);
 
 #ifdef CONFIG_SPARC64
-               /* ba,pt %xcc, . + (off << 2) */
-               val = 0x10680000 | ((u32) off >> 2);
-#else
-               /* ba . + (off << 2) */
-               val = 0x10800000 | ((u32) off >> 2);
+               if (off <= 0xfffff && off >= -0x100000)
+                       use_v9_branch = true;
 #endif
+               if (use_v9_branch) {
+                       /* WDISP19 - target is . + immed << 2 */
+                       /* ba,pt %xcc, . + off */
+                       val = 0x10680000 | (((u32) off >> 2) & 0x7ffff);
+               } else {
+                       /* WDISP22 - target is . + immed << 2 */
+                       BUG_ON(off > 0x7fffff);
+                       BUG_ON(off < -0x800000);
+                       /* ba . + off */
+                       val = 0x10800000 | (((u32) off >> 2) & 0x3fffff);
+               }
        } else {
                val = 0x01000000;
        }
index 1122886..8a6982d 100644 (file)
@@ -645,13 +645,20 @@ static void __mark_core_id(struct mdesc_handle *hp, u64 node,
                cpu_data(*id).core_id = core_id;
 }
 
-static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
-                          int sock_id)
+static void __mark_max_cache_id(struct mdesc_handle *hp, u64 node,
+                               int max_cache_id)
 {
        const u64 *id = mdesc_get_property(hp, node, "id", NULL);
 
-       if (*id < num_possible_cpus())
-               cpu_data(*id).sock_id = sock_id;
+       if (*id < num_possible_cpus()) {
+               cpu_data(*id).max_cache_id = max_cache_id;
+
+               /**
+                * On systems without explicit socket descriptions socket
+                * is max_cache_id
+                */
+               cpu_data(*id).sock_id = max_cache_id;
+       }
 }
 
 static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
@@ -660,10 +667,11 @@ static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
        find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
 }
 
-static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
-                         int sock_id)
+static void mark_max_cache_ids(struct mdesc_handle *hp, u64 mp,
+                              int max_cache_id)
 {
-       find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
+       find_back_node_value(hp, mp, "cpu", __mark_max_cache_id,
+                            max_cache_id, 10);
 }
 
 static void set_core_ids(struct mdesc_handle *hp)
@@ -694,14 +702,15 @@ static void set_core_ids(struct mdesc_handle *hp)
        }
 }
 
-static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
+static int set_max_cache_ids_by_cache(struct mdesc_handle *hp, int level)
 {
        u64 mp;
        int idx = 1;
        int fnd = 0;
 
-       /* Identify unique sockets by looking for cpus backpointed to by
-        * shared level n caches.
+       /**
+        * Identify unique highest level of shared cache by looking for cpus
+        * backpointed to by shared level N caches.
         */
        mdesc_for_each_node_by_name(hp, mp, "cache") {
                const u64 *cur_lvl;
@@ -709,8 +718,7 @@ static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
                cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
                if (*cur_lvl != level)
                        continue;
-
-               mark_sock_ids(hp, mp, idx);
+               mark_max_cache_ids(hp, mp, idx);
                idx++;
                fnd = 1;
        }
@@ -745,15 +753,17 @@ static void set_sock_ids(struct mdesc_handle *hp)
 {
        u64 mp;
 
-       /* If machine description exposes sockets data use it.
-        * Otherwise fallback to use shared L3 or L2 caches.
+       /**
+        * Find the highest level of shared cache which pre-T7 is also
+        * the socket.
         */
+       if (!set_max_cache_ids_by_cache(hp, 3))
+               set_max_cache_ids_by_cache(hp, 2);
+
+       /* If machine description exposes sockets data use it.*/
        mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
        if (mp != MDESC_NODE_NULL)
-               return set_sock_ids_by_socket(hp, mp);
-
-       if (!set_sock_ids_by_cache(hp, 3))
-               set_sock_ids_by_cache(hp, 2);
+               set_sock_ids_by_socket(hp, mp);
 }
 
 static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
index 9ddc492..ac082dd 100644 (file)
@@ -127,7 +127,8 @@ static int get_from_target(struct task_struct *target, unsigned long uaddr,
                if (copy_from_user(kbuf, (void __user *) uaddr, len))
                        return -EFAULT;
        } else {
-               int len2 = access_process_vm(target, uaddr, kbuf, len, 0);
+               int len2 = access_process_vm(target, uaddr, kbuf, len,
+                               FOLL_FORCE);
                if (len2 != len)
                        return -EFAULT;
        }
@@ -141,7 +142,8 @@ static int set_to_target(struct task_struct *target, unsigned long uaddr,
                if (copy_to_user((void __user *) uaddr, kbuf, len))
                        return -EFAULT;
        } else {
-               int len2 = access_process_vm(target, uaddr, kbuf, len, 1);
+               int len2 = access_process_vm(target, uaddr, kbuf, len,
+                               FOLL_FORCE | FOLL_WRITE);
                if (len2 != len)
                        return -EFAULT;
        }
@@ -505,7 +507,8 @@ static int genregs32_get(struct task_struct *target,
                                if (access_process_vm(target,
                                                      (unsigned long)
                                                      &reg_window[pos],
-                                                     k, sizeof(*k), 0)
+                                                     k, sizeof(*k),
+                                                     FOLL_FORCE)
                                    != sizeof(*k))
                                        return -EFAULT;
                                k++;
@@ -531,12 +534,14 @@ static int genregs32_get(struct task_struct *target,
                                if (access_process_vm(target,
                                                      (unsigned long)
                                                      &reg_window[pos],
-                                                     &reg, sizeof(reg), 0)
+                                                     &reg, sizeof(reg),
+                                                     FOLL_FORCE)
                                    != sizeof(reg))
                                        return -EFAULT;
                                if (access_process_vm(target,
                                                      (unsigned long) u,
-                                                     &reg, sizeof(reg), 1)
+                                                     &reg, sizeof(reg),
+                                                     FOLL_FORCE | FOLL_WRITE)
                                    != sizeof(reg))
                                        return -EFAULT;
                                pos++;
@@ -615,7 +620,8 @@ static int genregs32_set(struct task_struct *target,
                                                      (unsigned long)
                                                      &reg_window[pos],
                                                      (void *) k,
-                                                     sizeof(*k), 1)
+                                                     sizeof(*k),
+                                                     FOLL_FORCE | FOLL_WRITE)
                                    != sizeof(*k))
                                        return -EFAULT;
                                k++;
@@ -642,13 +648,15 @@ static int genregs32_set(struct task_struct *target,
                                if (access_process_vm(target,
                                                      (unsigned long)
                                                      u,
-                                                     &reg, sizeof(reg), 0)
+                                                     &reg, sizeof(reg),
+                                                     FOLL_FORCE)
                                    != sizeof(reg))
                                        return -EFAULT;
                                if (access_process_vm(target,
                                                      (unsigned long)
                                                      &reg_window[pos],
-                                                     &reg, sizeof(reg), 1)
+                                                     &reg, sizeof(reg),
+                                                     FOLL_FORCE | FOLL_WRITE)
                                    != sizeof(reg))
                                        return -EFAULT;
                                pos++;
index d3035ba..8182f7c 100644 (file)
@@ -63,9 +63,13 @@ cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
 cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = {
        [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 
+cpumask_t cpu_core_sib_cache_map[NR_CPUS] __read_mostly = {
+       [0 ... NR_CPUS - 1] = CPU_MASK_NONE };
+
 EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
 EXPORT_SYMBOL(cpu_core_map);
 EXPORT_SYMBOL(cpu_core_sib_map);
+EXPORT_SYMBOL(cpu_core_sib_cache_map);
 
 static cpumask_t smp_commenced_mask;
 
@@ -1265,6 +1269,10 @@ void smp_fill_in_sib_core_maps(void)
                unsigned int j;
 
                for_each_present_cpu(j)  {
+                       if (cpu_data(i).max_cache_id ==
+                           cpu_data(j).max_cache_id)
+                               cpumask_set_cpu(j, &cpu_core_sib_cache_map[i]);
+
                        if (cpu_data(i).sock_id == cpu_data(j).sock_id)
                                cpumask_set_cpu(j, &cpu_core_sib_map[i]);
                }
index b7d0bd6..69a439f 100644 (file)
@@ -3,11 +3,11 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index 780550e..9947427 100644 (file)
@@ -3,11 +3,11 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index 89358ee..059ea24 100644 (file)
@@ -4,21 +4,18 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #define GLOBAL_SPARE   %g7
 #else
 #define GLOBAL_SPARE   %g5
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
+#define EX_ST(x,y)     x
 #endif
 
 #ifndef LOAD
        .register       %g3,#scratch
 
        .text
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+ENTRY(GEN_retl_o4_1)
+       add     %o4, %o2, %o4
+       retl
+        add    %o4, 1, %o0
+ENDPROC(GEN_retl_o4_1)
+ENTRY(GEN_retl_g1_8)
+       add     %g1, %o2, %g1
+       retl
+        add    %g1, 8, %o0
+ENDPROC(GEN_retl_g1_8)
+ENTRY(GEN_retl_o2_4)
+       retl
+        add    %o2, 4, %o0
+ENDPROC(GEN_retl_o2_4)
+ENTRY(GEN_retl_o2_1)
+       retl
+        add    %o2, 1, %o0
+ENDPROC(GEN_retl_o2_1)
+#endif
+
        .align          64
 
        .globl  FUNC_NAME
@@ -73,8 +93,8 @@ FUNC_NAME:    /* %o0=dst, %o1=src, %o2=len */
        sub             %g0, %o4, %o4
        sub             %o2, %o4, %o2
 1:     subcc           %o4, 1, %o4
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o0))
+       EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o4_1)
+       EX_ST(STORE(stb, %g1, %o0),GEN_retl_o4_1)
        add             %o1, 1, %o1
        bne,pt          %XCC, 1b
        add             %o0, 1, %o0
@@ -82,8 +102,8 @@ FUNC_NAME:   /* %o0=dst, %o1=src, %o2=len */
        andn            %o2, 0x7, %g1
        sub             %o2, %g1, %o2
 1:     subcc           %g1, 0x8, %g1
-       EX_LD(LOAD(ldx, %o1, %g2))
-       EX_ST(STORE(stx, %g2, %o0))
+       EX_LD(LOAD(ldx, %o1, %g2),GEN_retl_g1_8)
+       EX_ST(STORE(stx, %g2, %o0),GEN_retl_g1_8)
        add             %o1, 0x8, %o1
        bne,pt          %XCC, 1b
         add            %o0, 0x8, %o0
@@ -100,8 +120,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
 
 1:
        subcc           %o2, 4, %o2
-       EX_LD(LOAD(lduw, %o1, %g1))
-       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       EX_LD(LOAD(lduw, %o1, %g1),GEN_retl_o2_4)
+       EX_ST(STORE(stw, %g1, %o1 + %o3),GEN_retl_o2_4)
        bgu,pt          %XCC, 1b
         add            %o1, 4, %o1
 
@@ -111,8 +131,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        .align          32
 90:
        subcc           %o2, 1, %o2
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       EX_LD(LOAD(ldub, %o1, %g1),GEN_retl_o2_1)
+       EX_ST(STORE(stb, %g1, %o1 + %o3),GEN_retl_o2_1)
        bgu,pt          %XCC, 90b
         add            %o1, 1, %o1
        retl
index 885f00e..69912d2 100644 (file)
@@ -38,7 +38,7 @@ lib-$(CONFIG_SPARC64) +=  NG4patch.o NG4copy_page.o NG4clear_page.o NG4memset.o
 lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
 lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
 
-lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
+lib-$(CONFIG_SPARC64) += copy_in_user.o memmove.o
 lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
 
 obj-$(CONFIG_SPARC64) += iomap.o
index d5242b8..b79a699 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_LD_FP(x)            \
+#define EX_LD_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index 4e962d9..dcec55f 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_ST_FP(x)            \
+#define EX_ST_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index d5f585d..c629dbd 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE   %g7
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)    x
+#define EX_LD_FP(x,y)  x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
+#define EX_ST(x,y)     x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)    x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
+#define EX_ST_FP(x,y)  x
 #endif
 
 #ifndef LOAD
        fsrc2           %x6, %f12; \
        fsrc2           %x7, %f14;
 #define FREG_LOAD_1(base, x0) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0))
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1)
 #define FREG_LOAD_2(base, x0, x1) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_3(base, x0, x1, x2) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD_FP(LOAD(ldd, base + 0x10, %x2));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_4(base, x0, x1, x2, x3) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD_FP(LOAD(ldd, base + 0x18, %x3));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD_FP(LOAD(ldd, base + 0x20, %x4));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
-       EX_LD_FP(LOAD(ldd, base + 0x28, %x5));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1);
 #define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
-       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
-       EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); \
-       EX_LD_FP(LOAD(ldd, base + 0x30, %x6));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x28, %x5), NG2_retl_o2_plus_g1); \
+       EX_LD_FP(LOAD(ldd, base + 0x30, %x6), NG2_retl_o2_plus_g1);
 
        .register       %g2,#scratch
        .register       %g3,#scratch
 
        .text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+__restore_fp:
+       VISExitHalf
+__restore_asi:
+       retl
+        wr     %g0, ASI_AIUS, %asi
+ENTRY(NG2_retl_o2)
+       ba,pt   %xcc, __restore_asi
+        mov    %o2, %o0
+ENDPROC(NG2_retl_o2)
+ENTRY(NG2_retl_o2_plus_1)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, 1, %o0
+ENDPROC(NG2_retl_o2_plus_1)
+ENTRY(NG2_retl_o2_plus_4)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, 4, %o0
+ENDPROC(NG2_retl_o2_plus_4)
+ENTRY(NG2_retl_o2_plus_8)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, 8, %o0
+ENDPROC(NG2_retl_o2_plus_8)
+ENTRY(NG2_retl_o2_plus_o4_plus_1)
+       add     %o4, 1, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_1)
+ENTRY(NG2_retl_o2_plus_o4_plus_8)
+       add     %o4, 8, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_8)
+ENTRY(NG2_retl_o2_plus_o4_plus_16)
+       add     %o4, 16, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG2_retl_o2_plus_o4_plus_16)
+ENTRY(NG2_retl_o2_plus_g1_fp)
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_fp)
+ENTRY(NG2_retl_o2_plus_g1_plus_64_fp)
+       add     %g1, 64, %g1
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_plus_64_fp)
+ENTRY(NG2_retl_o2_plus_g1_plus_1)
+       add     %g1, 1, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %g1, %o0
+ENDPROC(NG2_retl_o2_plus_g1_plus_1)
+ENTRY(NG2_retl_o2_and_7_plus_o4)
+       and     %o2, 7, %o2
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG2_retl_o2_and_7_plus_o4)
+ENTRY(NG2_retl_o2_and_7_plus_o4_plus_8)
+       and     %o2, 7, %o2
+       add     %o4, 8, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG2_retl_o2_and_7_plus_o4_plus_8)
+#endif
+
        .align          64
 
        .globl  FUNC_NAME
@@ -230,8 +292,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        sub             %g0, %o4, %o4   ! bytes to align dst
        sub             %o2, %o4, %o2
 1:     subcc           %o4, 1, %o4
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o0))
+       EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_o4_plus_1)
+       EX_ST(STORE(stb, %g1, %o0), NG2_retl_o2_plus_o4_plus_1)
        add             %o1, 1, %o1
        bne,pt          %XCC, 1b
        add             %o0, 1, %o0
@@ -281,11 +343,11 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         nop
        /* fall through for 0 < low bits < 8 */
 110:   sub             %o4, 64, %g2
-       EX_LD_FP(LOAD_BLK(%g2, %f0))
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+       EX_LD_FP(LOAD_BLK(%g2, %f0), NG2_retl_o2_plus_g1)
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -296,10 +358,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 120:   sub             %o4, 56, %g2
        FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -310,10 +372,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 130:   sub             %o4, 48, %g2
        FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -324,10 +386,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 140:   sub             %o4, 40, %g2
        FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_5(f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -338,10 +400,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 150:   sub             %o4, 32, %g2
        FREG_LOAD_4(%g2, f0, f2, f4, f6)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_4(f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -352,10 +414,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 160:   sub             %o4, 24, %g2
        FREG_LOAD_3(%g2, f0, f2, f4)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_3(f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -366,10 +428,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 170:   sub             %o4, 16, %g2
        FREG_LOAD_2(%g2, f0, f2)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_2(f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -380,10 +442,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 180:   sub             %o4, 8, %g2
        FREG_LOAD_1(%g2, f0)
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD_FP(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
+       EX_LD_FP(LOAD_BLK(%o4, %f16), NG2_retl_o2_plus_g1)
        FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1)
        FREG_MOVE_1(f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -393,10 +455,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         nop
 
 190:
-1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3), NG2_retl_o2_plus_g1)
        subcc           %g1, 64, %g1
-       EX_LD_FP(LOAD_BLK(%o4, %f0))
-       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f0), NG2_retl_o2_plus_g1_plus_64)
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3), NG2_retl_o2_plus_g1_plus_64)
        add             %o4, 64, %o4
        bne,pt          %xcc, 1b
         LOAD(prefetch, %o4 + 64, #one_read)
@@ -423,28 +485,28 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        andn            %o2, 0xf, %o4
        and             %o2, 0xf, %o2
 1:     subcc           %o4, 0x10, %o4
-       EX_LD(LOAD(ldx, %o1, %o5))
+       EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_o4_plus_16)
        add             %o1, 0x08, %o1
-       EX_LD(LOAD(ldx, %o1, %g1))
+       EX_LD(LOAD(ldx, %o1, %g1), NG2_retl_o2_plus_o4_plus_16)
        sub             %o1, 0x08, %o1
-       EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE))
+       EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_16)
        add             %o1, 0x8, %o1
-       EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE))
+       EX_ST(STORE(stx, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_o4_plus_8)
        bgu,pt          %XCC, 1b
         add            %o1, 0x8, %o1
 73:    andcc           %o2, 0x8, %g0
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x8, %o2
-       EX_LD(LOAD(ldx, %o1, %o5))
-       EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE))
+       EX_LD(LOAD(ldx, %o1, %o5), NG2_retl_o2_plus_8)
+       EX_ST(STORE(stx, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_8)
        add             %o1, 0x8, %o1
 1:     andcc           %o2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x4, %o2
-       EX_LD(LOAD(lduw, %o1, %o5))
-       EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE))
+       EX_LD(LOAD(lduw, %o1, %o5), NG2_retl_o2_plus_4)
+       EX_ST(STORE(stw, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
        add             %o1, 0x4, %o1
 1:     cmp             %o2, 0
        be,pt           %XCC, 85f
@@ -460,8 +522,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        sub             %o2, %g1, %o2
 
 1:     subcc           %g1, 1, %g1
-       EX_LD(LOAD(ldub, %o1, %o5))
-       EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE))
+       EX_LD(LOAD(ldub, %o1, %o5), NG2_retl_o2_plus_g1_plus_1)
+       EX_ST(STORE(stb, %o5, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_g1_plus_1)
        bgu,pt          %icc, 1b
         add            %o1, 1, %o1
 
@@ -477,16 +539,16 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 8:     mov             64, GLOBAL_SPARE
        andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1, %g2))
+       EX_LD(LOAD(ldx, %o1, %g2), NG2_retl_o2)
        sub             GLOBAL_SPARE, %g1, GLOBAL_SPARE
        andn            %o2, 0x7, %o4
        sllx            %g2, %g1, %g2
 1:     add             %o1, 0x8, %o1
-       EX_LD(LOAD(ldx, %o1, %g3))
+       EX_LD(LOAD(ldx, %o1, %g3), NG2_retl_o2_and_7_plus_o4)
        subcc           %o4, 0x8, %o4
        srlx            %g3, GLOBAL_SPARE, %o5
        or              %o5, %g2, %o5
-       EX_ST(STORE(stx, %o5, %o0))
+       EX_ST(STORE(stx, %o5, %o0), NG2_retl_o2_and_7_plus_o4_plus_8)
        add             %o0, 0x8, %o0
        bgu,pt          %icc, 1b
         sllx           %g3, %g1, %g2
@@ -506,8 +568,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
 
 1:
        subcc           %o2, 4, %o2
-       EX_LD(LOAD(lduw, %o1, %g1))
-       EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE))
+       EX_LD(LOAD(lduw, %o1, %g1), NG2_retl_o2_plus_4)
+       EX_ST(STORE(stw, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_4)
        bgu,pt          %XCC, 1b
         add            %o1, 4, %o1
 
@@ -517,8 +579,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        .align          32
 90:
        subcc           %o2, 1, %o2
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE))
+       EX_LD(LOAD(ldub, %o1, %g1), NG2_retl_o2_plus_1)
+       EX_ST(STORE(stb, %g1, %o1 + GLOBAL_SPARE), NG2_retl_o2_plus_1)
        bgu,pt          %XCC, 90b
         add            %o1, 1, %o1
        retl
index 2e8ee7a..16a286c 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 2012 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x, y)            \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_LD_FP(x)            \
+#define EX_LD_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index be0bf45..6b0276f 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 2012 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_ST_FP(x)            \
+#define EX_ST_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_asi_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index 8e13ee1..75bb93b 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE   %g7
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)    x
+#define EX_LD_FP(x,y)  x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
+#define EX_ST(x,y)     x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)    x
+#define EX_ST_FP(x,y)  x
 #endif
 
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
-#endif
 
 #ifndef LOAD
 #define LOAD(type,addr,dest)   type [addr], dest
        .register       %g3,#scratch
 
        .text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+__restore_asi_fp:
+       VISExitHalf
+__restore_asi:
+       retl
+        wr     %g0, ASI_AIUS, %asi
+
+ENTRY(NG4_retl_o2)
+       ba,pt   %xcc, __restore_asi
+        mov    %o2, %o0
+ENDPROC(NG4_retl_o2)
+ENTRY(NG4_retl_o2_plus_1)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, 1, %o0
+ENDPROC(NG4_retl_o2_plus_1)
+ENTRY(NG4_retl_o2_plus_4)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, 4, %o0
+ENDPROC(NG4_retl_o2_plus_4)
+ENTRY(NG4_retl_o2_plus_o5)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5)
+ENTRY(NG4_retl_o2_plus_o5_plus_4)
+       add     %o5, 4, %o5
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_4)
+ENTRY(NG4_retl_o2_plus_o5_plus_8)
+       add     %o5, 8, %o5
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_8)
+ENTRY(NG4_retl_o2_plus_o5_plus_16)
+       add     %o5, 16, %o5
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_16)
+ENTRY(NG4_retl_o2_plus_o5_plus_24)
+       add     %o5, 24, %o5
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_24)
+ENTRY(NG4_retl_o2_plus_o5_plus_32)
+       add     %o5, 32, %o5
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o5, %o0
+ENDPROC(NG4_retl_o2_plus_o5_plus_32)
+ENTRY(NG4_retl_o2_plus_g1)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1)
+ENTRY(NG4_retl_o2_plus_g1_plus_1)
+       add     %g1, 1, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1_plus_1)
+ENTRY(NG4_retl_o2_plus_g1_plus_8)
+       add     %g1, 8, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %g1, %o0
+ENDPROC(NG4_retl_o2_plus_g1_plus_8)
+ENTRY(NG4_retl_o2_plus_o4)
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4)
+ENTRY(NG4_retl_o2_plus_o4_plus_8)
+       add     %o4, 8, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_8)
+ENTRY(NG4_retl_o2_plus_o4_plus_16)
+       add     %o4, 16, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_16)
+ENTRY(NG4_retl_o2_plus_o4_plus_24)
+       add     %o4, 24, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_24)
+ENTRY(NG4_retl_o2_plus_o4_plus_32)
+       add     %o4, 32, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_32)
+ENTRY(NG4_retl_o2_plus_o4_plus_40)
+       add     %o4, 40, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_40)
+ENTRY(NG4_retl_o2_plus_o4_plus_48)
+       add     %o4, 48, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_48)
+ENTRY(NG4_retl_o2_plus_o4_plus_56)
+       add     %o4, 56, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_56)
+ENTRY(NG4_retl_o2_plus_o4_plus_64)
+       add     %o4, 64, %o4
+       ba,pt   %xcc, __restore_asi
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_64)
+ENTRY(NG4_retl_o2_plus_o4_fp)
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_8_fp)
+       add     %o4, 8, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_8_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_16_fp)
+       add     %o4, 16, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_16_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_24_fp)
+       add     %o4, 24, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_24_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_32_fp)
+       add     %o4, 32, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_32_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_40_fp)
+       add     %o4, 40, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_40_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_48_fp)
+       add     %o4, 48, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_48_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_56_fp)
+       add     %o4, 56, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_56_fp)
+ENTRY(NG4_retl_o2_plus_o4_plus_64_fp)
+       add     %o4, 64, %o4
+       ba,pt   %xcc, __restore_asi_fp
+        add    %o2, %o4, %o0
+ENDPROC(NG4_retl_o2_plus_o4_plus_64_fp)
+#endif
        .align          64
 
        .globl  FUNC_NAME
@@ -124,12 +274,13 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        brz,pt          %g1, 51f
         sub            %o2, %g1, %o2
 
-1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g2))
+
+1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
        add             %o1, 1, %o1
        subcc           %g1, 1, %g1
        add             %o0, 1, %o0
        bne,pt          %icc, 1b
-        EX_ST(STORE(stb, %g2, %o0 - 0x01))
+        EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1)
 
 51:    LOAD(prefetch, %o1 + 0x040, #n_reads_strong)
        LOAD(prefetch, %o1 + 0x080, #n_reads_strong)
@@ -154,43 +305,43 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        brz,pt          %g1, .Llarge_aligned
         sub            %o2, %g1, %o2
 
-1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g2))
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
        add             %o1, 8, %o1
        subcc           %g1, 8, %g1
        add             %o0, 8, %o0
        bne,pt          %icc, 1b
-        EX_ST(STORE(stx, %g2, %o0 - 0x08))
+        EX_ST(STORE(stx, %g2, %o0 - 0x08), NG4_retl_o2_plus_g1_plus_8)
 
 .Llarge_aligned:
        /* len >= 0x80 && src 8-byte aligned && dest 8-byte aligned */
        andn            %o2, 0x3f, %o4
        sub             %o2, %o4, %o2
 
-1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o4)
        add             %o1, 0x40, %o1
-       EX_LD(LOAD(ldx, %o1 - 0x38, %g2))
+       EX_LD(LOAD(ldx, %o1 - 0x38, %g2), NG4_retl_o2_plus_o4)
        subcc           %o4, 0x40, %o4
-       EX_LD(LOAD(ldx, %o1 - 0x30, %g3))
-       EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE))
-       EX_LD(LOAD(ldx, %o1 - 0x20, %o5))
-       EX_ST(STORE_INIT(%g1, %o0))
+       EX_LD(LOAD(ldx, %o1 - 0x30, %g3), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD(LOAD(ldx, %o1 - 0x28, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD(LOAD(ldx, %o1 - 0x20, %o5), NG4_retl_o2_plus_o4_plus_64)
+       EX_ST(STORE_INIT(%g1, %o0), NG4_retl_o2_plus_o4_plus_64)
        add             %o0, 0x08, %o0
-       EX_ST(STORE_INIT(%g2, %o0))
+       EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_56)
        add             %o0, 0x08, %o0
-       EX_LD(LOAD(ldx, %o1 - 0x18, %g2))
-       EX_ST(STORE_INIT(%g3, %o0))
+       EX_LD(LOAD(ldx, %o1 - 0x18, %g2), NG4_retl_o2_plus_o4_plus_48)
+       EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_48)
        add             %o0, 0x08, %o0
-       EX_LD(LOAD(ldx, %o1 - 0x10, %g3))
-       EX_ST(STORE_INIT(GLOBAL_SPARE, %o0))
+       EX_LD(LOAD(ldx, %o1 - 0x10, %g3), NG4_retl_o2_plus_o4_plus_40)
+       EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_40)
        add             %o0, 0x08, %o0
-       EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE))
-       EX_ST(STORE_INIT(%o5, %o0))
+       EX_LD(LOAD(ldx, %o1 - 0x08, GLOBAL_SPARE), NG4_retl_o2_plus_o4_plus_32)
+       EX_ST(STORE_INIT(%o5, %o0), NG4_retl_o2_plus_o4_plus_32)
        add             %o0, 0x08, %o0
-       EX_ST(STORE_INIT(%g2, %o0))
+       EX_ST(STORE_INIT(%g2, %o0), NG4_retl_o2_plus_o4_plus_24)
        add             %o0, 0x08, %o0
-       EX_ST(STORE_INIT(%g3, %o0))
+       EX_ST(STORE_INIT(%g3, %o0), NG4_retl_o2_plus_o4_plus_16)
        add             %o0, 0x08, %o0
-       EX_ST(STORE_INIT(GLOBAL_SPARE, %o0))
+       EX_ST(STORE_INIT(GLOBAL_SPARE, %o0), NG4_retl_o2_plus_o4_plus_8)
        add             %o0, 0x08, %o0
        bne,pt          %icc, 1b
         LOAD(prefetch, %o1 + 0x200, #n_reads_strong)
@@ -216,17 +367,17 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        sub             %o2, %o4, %o2
        alignaddr       %o1, %g0, %g1
        add             %o1, %o4, %o1
-       EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0))
-1:     EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0), NG4_retl_o2_plus_o4)
+1:     EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2), NG4_retl_o2_plus_o4)
        subcc           %o4, 0x40, %o4
-       EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4))
-       EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6))
-       EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8))
-       EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10))
-       EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12))
-       EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12), NG4_retl_o2_plus_o4_plus_64)
+       EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14), NG4_retl_o2_plus_o4_plus_64)
        faligndata      %f0, %f2, %f16
-       EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0), NG4_retl_o2_plus_o4_plus_64)
        faligndata      %f2, %f4, %f18
        add             %g1, 0x40, %g1
        faligndata      %f4, %f6, %f20
@@ -235,14 +386,14 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        faligndata      %f10, %f12, %f26
        faligndata      %f12, %f14, %f28
        faligndata      %f14, %f0, %f30
-       EX_ST_FP(STORE(std, %f16, %o0 + 0x00))
-       EX_ST_FP(STORE(std, %f18, %o0 + 0x08))
-       EX_ST_FP(STORE(std, %f20, %o0 + 0x10))
-       EX_ST_FP(STORE(std, %f22, %o0 + 0x18))
-       EX_ST_FP(STORE(std, %f24, %o0 + 0x20))
-       EX_ST_FP(STORE(std, %f26, %o0 + 0x28))
-       EX_ST_FP(STORE(std, %f28, %o0 + 0x30))
-       EX_ST_FP(STORE(std, %f30, %o0 + 0x38))
+       EX_ST_FP(STORE(std, %f16, %o0 + 0x00), NG4_retl_o2_plus_o4_plus_64)
+       EX_ST_FP(STORE(std, %f18, %o0 + 0x08), NG4_retl_o2_plus_o4_plus_56)
+       EX_ST_FP(STORE(std, %f20, %o0 + 0x10), NG4_retl_o2_plus_o4_plus_48)
+       EX_ST_FP(STORE(std, %f22, %o0 + 0x18), NG4_retl_o2_plus_o4_plus_40)
+       EX_ST_FP(STORE(std, %f24, %o0 + 0x20), NG4_retl_o2_plus_o4_plus_32)
+       EX_ST_FP(STORE(std, %f26, %o0 + 0x28), NG4_retl_o2_plus_o4_plus_24)
+       EX_ST_FP(STORE(std, %f28, %o0 + 0x30), NG4_retl_o2_plus_o4_plus_16)
+       EX_ST_FP(STORE(std, %f30, %o0 + 0x38), NG4_retl_o2_plus_o4_plus_8)
        add             %o0, 0x40, %o0
        bne,pt          %icc, 1b
         LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
@@ -270,37 +421,38 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        andncc          %o2, 0x20 - 1, %o5
        be,pn           %icc, 2f
         sub            %o2, %o5, %o2
-1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
-       EX_LD(LOAD(ldx, %o1 + 0x08, %g2))
-       EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE))
-       EX_LD(LOAD(ldx, %o1 + 0x18, %o4))
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
+       EX_LD(LOAD(ldx, %o1 + 0x08, %g2), NG4_retl_o2_plus_o5)
+       EX_LD(LOAD(ldx, %o1 + 0x10, GLOBAL_SPARE), NG4_retl_o2_plus_o5)
+       EX_LD(LOAD(ldx, %o1 + 0x18, %o4), NG4_retl_o2_plus_o5)
        add             %o1, 0x20, %o1
        subcc           %o5, 0x20, %o5
-       EX_ST(STORE(stx, %g1, %o0 + 0x00))
-       EX_ST(STORE(stx, %g2, %o0 + 0x08))
-       EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10))
-       EX_ST(STORE(stx, %o4, %o0 + 0x18))
+       EX_ST(STORE(stx, %g1, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_32)
+       EX_ST(STORE(stx, %g2, %o0 + 0x08), NG4_retl_o2_plus_o5_plus_24)
+       EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x10), NG4_retl_o2_plus_o5_plus_24)
+       EX_ST(STORE(stx, %o4, %o0 + 0x18), NG4_retl_o2_plus_o5_plus_8)
        bne,pt          %icc, 1b
         add            %o0, 0x20, %o0
 2:     andcc           %o2, 0x18, %o5
        be,pt           %icc, 3f
         sub            %o2, %o5, %o2
-1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1))
+
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
        add             %o1, 0x08, %o1
        add             %o0, 0x08, %o0
        subcc           %o5, 0x08, %o5
        bne,pt          %icc, 1b
-        EX_ST(STORE(stx, %g1, %o0 - 0x08))
+        EX_ST(STORE(stx, %g1, %o0 - 0x08), NG4_retl_o2_plus_o5_plus_8)
 3:     brz,pt          %o2, .Lexit
         cmp            %o2, 0x04
        bl,pn           %icc, .Ltiny
         nop
-       EX_LD(LOAD(lduw, %o1 + 0x00, %g1))
+       EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2)
        add             %o1, 0x04, %o1
        add             %o0, 0x04, %o0
        subcc           %o2, 0x04, %o2
        bne,pn          %icc, .Ltiny
-        EX_ST(STORE(stw, %g1, %o0 - 0x04))
+        EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_4)
        ba,a,pt         %icc, .Lexit
 .Lmedium_unaligned:
        /* First get dest 8 byte aligned.  */
@@ -309,12 +461,12 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        brz,pt          %g1, 2f
         sub            %o2, %g1, %o2
 
-1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g2))
+1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g2), NG4_retl_o2_plus_g1)
        add             %o1, 1, %o1
        subcc           %g1, 1, %g1
        add             %o0, 1, %o0
        bne,pt          %icc, 1b
-        EX_ST(STORE(stb, %g2, %o0 - 0x01))
+        EX_ST(STORE(stb, %g2, %o0 - 0x01), NG4_retl_o2_plus_g1_plus_1)
 2:
        and             %o1, 0x7, %g1
        brz,pn          %g1, .Lmedium_noprefetch
@@ -322,16 +474,16 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        mov             64, %g2
        sub             %g2, %g1, %g2
        andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1 + 0x00, %o4))
+       EX_LD(LOAD(ldx, %o1 + 0x00, %o4), NG4_retl_o2)
        sllx            %o4, %g1, %o4
        andn            %o2, 0x08 - 1, %o5
        sub             %o2, %o5, %o2
-1:     EX_LD(LOAD(ldx, %o1 + 0x08, %g3))
+1:     EX_LD(LOAD(ldx, %o1 + 0x08, %g3), NG4_retl_o2_plus_o5)
        add             %o1, 0x08, %o1
        subcc           %o5, 0x08, %o5
        srlx            %g3, %g2, GLOBAL_SPARE
        or              GLOBAL_SPARE, %o4, GLOBAL_SPARE
-       EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00))
+       EX_ST(STORE(stx, GLOBAL_SPARE, %o0 + 0x00), NG4_retl_o2_plus_o5_plus_8)
        add             %o0, 0x08, %o0
        bne,pt          %icc, 1b
         sllx           %g3, %g1, %o4
@@ -342,17 +494,17 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        ba,pt           %icc, .Lsmall_unaligned
 
 .Ltiny:
-       EX_LD(LOAD(ldub, %o1 + 0x00, %g1))
+       EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2)
        subcc           %o2, 1, %o2
        be,pn           %icc, .Lexit
-        EX_ST(STORE(stb, %g1, %o0 + 0x00))
-       EX_LD(LOAD(ldub, %o1 + 0x01, %g1))
+        EX_ST(STORE(stb, %g1, %o0 + 0x00), NG4_retl_o2_plus_1)
+       EX_LD(LOAD(ldub, %o1 + 0x01, %g1), NG4_retl_o2)
        subcc           %o2, 1, %o2
        be,pn           %icc, .Lexit
-        EX_ST(STORE(stb, %g1, %o0 + 0x01))
-       EX_LD(LOAD(ldub, %o1 + 0x02, %g1))
+        EX_ST(STORE(stb, %g1, %o0 + 0x01), NG4_retl_o2_plus_1)
+       EX_LD(LOAD(ldub, %o1 + 0x02, %g1), NG4_retl_o2)
        ba,pt           %icc, .Lexit
-        EX_ST(STORE(stb, %g1, %o0 + 0x02))
+        EX_ST(STORE(stb, %g1, %o0 + 0x02), NG4_retl_o2)
 
 .Lsmall:
        andcc           %g2, 0x3, %g0
@@ -360,22 +512,22 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         andn           %o2, 0x4 - 1, %o5
        sub             %o2, %o5, %o2
 1:
-       EX_LD(LOAD(lduw, %o1 + 0x00, %g1))
+       EX_LD(LOAD(lduw, %o1 + 0x00, %g1), NG4_retl_o2_plus_o5)
        add             %o1, 0x04, %o1
        subcc           %o5, 0x04, %o5
        add             %o0, 0x04, %o0
        bne,pt          %icc, 1b
-        EX_ST(STORE(stw, %g1, %o0 - 0x04))
+        EX_ST(STORE(stw, %g1, %o0 - 0x04), NG4_retl_o2_plus_o5_plus_4)
        brz,pt          %o2, .Lexit
         nop
        ba,a,pt         %icc, .Ltiny
 
 .Lsmall_unaligned:
-1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g1))
+1:     EX_LD(LOAD(ldub, %o1 + 0x00, %g1), NG4_retl_o2)
        add             %o1, 1, %o1
        add             %o0, 1, %o0
        subcc           %o2, 1, %o2
        bne,pt          %icc, 1b
-        EX_ST(STORE(stb, %g1, %o0 - 0x01))
+        EX_ST(STORE(stb, %g1, %o0 - 0x01), NG4_retl_o2_plus_1)
        ba,a,pt         %icc, .Lexit
        .size           FUNC_NAME, .-FUNC_NAME
index 5d1e4d1..9cd42fc 100644 (file)
@@ -3,11 +3,11 @@
  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __ret_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index ff630dc..5c358af 100644 (file)
@@ -3,11 +3,11 @@
  * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __ret_one_asi;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index 96a14ca..d88c4ed 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/asi.h>
 #include <asm/thread_info.h>
 #define GLOBAL_SPARE   %g7
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
+#define EX_ST(x,y)     x
 #endif
 
 #ifndef LOAD
        .register       %g3,#scratch
 
        .text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+__restore_asi:
+       ret
+       wr      %g0, ASI_AIUS, %asi
+        restore
+ENTRY(NG_ret_i2_plus_i4_plus_1)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %i5, %i0
+ENDPROC(NG_ret_i2_plus_i4_plus_1)
+ENTRY(NG_ret_i2_plus_g1)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1)
+ENTRY(NG_ret_i2_plus_g1_minus_8)
+       sub     %g1, 8, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_8)
+ENTRY(NG_ret_i2_plus_g1_minus_16)
+       sub     %g1, 16, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_16)
+ENTRY(NG_ret_i2_plus_g1_minus_24)
+       sub     %g1, 24, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_24)
+ENTRY(NG_ret_i2_plus_g1_minus_32)
+       sub     %g1, 32, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_32)
+ENTRY(NG_ret_i2_plus_g1_minus_40)
+       sub     %g1, 40, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_40)
+ENTRY(NG_ret_i2_plus_g1_minus_48)
+       sub     %g1, 48, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_48)
+ENTRY(NG_ret_i2_plus_g1_minus_56)
+       sub     %g1, 56, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_minus_56)
+ENTRY(NG_ret_i2_plus_i4)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %i4, %i0
+ENDPROC(NG_ret_i2_plus_i4)
+ENTRY(NG_ret_i2_plus_i4_minus_8)
+       sub     %i4, 8, %i4
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %i4, %i0
+ENDPROC(NG_ret_i2_plus_i4_minus_8)
+ENTRY(NG_ret_i2_plus_8)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, 8, %i0
+ENDPROC(NG_ret_i2_plus_8)
+ENTRY(NG_ret_i2_plus_4)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, 4, %i0
+ENDPROC(NG_ret_i2_plus_4)
+ENTRY(NG_ret_i2_plus_1)
+       ba,pt   %xcc, __restore_asi
+        add    %i2, 1, %i0
+ENDPROC(NG_ret_i2_plus_1)
+ENTRY(NG_ret_i2_plus_g1_plus_1)
+       add     %g1, 1, %g1
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %g1, %i0
+ENDPROC(NG_ret_i2_plus_g1_plus_1)
+ENTRY(NG_ret_i2)
+       ba,pt   %xcc, __restore_asi
+        mov    %i2, %i0
+ENDPROC(NG_ret_i2)
+ENTRY(NG_ret_i2_and_7_plus_i4)
+       and     %i2, 7, %i2
+       ba,pt   %xcc, __restore_asi
+        add    %i2, %i4, %i0
+ENDPROC(NG_ret_i2_and_7_plus_i4)
+#endif
+
        .align          64
 
        .globl  FUNC_NAME
@@ -126,8 +209,8 @@ FUNC_NAME:  /* %i0=dst, %i1=src, %i2=len */
        sub             %g0, %i4, %i4   ! bytes to align dst
        sub             %i2, %i4, %i2
 1:     subcc           %i4, 1, %i4
-       EX_LD(LOAD(ldub, %i1, %g1))
-       EX_ST(STORE(stb, %g1, %o0))
+       EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_i4_plus_1)
+       EX_ST(STORE(stb, %g1, %o0), NG_ret_i2_plus_i4_plus_1)
        add             %i1, 1, %i1
        bne,pt          %XCC, 1b
        add             %o0, 1, %o0
@@ -160,7 +243,7 @@ FUNC_NAME:  /* %i0=dst, %i1=src, %i2=len */
        and             %i4, 0x7, GLOBAL_SPARE
        sll             GLOBAL_SPARE, 3, GLOBAL_SPARE
        mov             64, %i5
-       EX_LD(LOAD_TWIN(%i1, %g2, %g3))
+       EX_LD(LOAD_TWIN(%i1, %g2, %g3), NG_ret_i2_plus_g1)
        sub             %i5, GLOBAL_SPARE, %i5
        mov             16, %o4
        mov             32, %o5
@@ -178,31 +261,31 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
        srlx            WORD3, PRE_SHIFT, TMP; \
        or              WORD2, TMP, WORD2;
 
-8:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+8:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1)
        MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
        LOAD(prefetch, %i1 + %i3, #one_read)
 
-       EX_ST(STORE_INIT(%g2, %o0 + 0x00))
-       EX_ST(STORE_INIT(%g3, %o0 + 0x08))
+       EX_ST(STORE_INIT(%g2, %o0 + 0x00), NG_ret_i2_plus_g1)
+       EX_ST(STORE_INIT(%g3, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
 
-       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16)
        MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%o2, %o0 + 0x10))
-       EX_ST(STORE_INIT(%o3, %o0 + 0x18))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
 
-       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
        MIX_THREE_WORDS(%g2, %g3, %o2, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%g2, %o0 + 0x20))
-       EX_ST(STORE_INIT(%g3, %o0 + 0x28))
+       EX_ST(STORE_INIT(%g2, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+       EX_ST(STORE_INIT(%g3, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
 
-       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48)
        add             %i1, 64, %i1
        MIX_THREE_WORDS(%o2, %o3, %g2, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%o2, %o0 + 0x30))
-       EX_ST(STORE_INIT(%o3, %o0 + 0x38))
+       EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+       EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 
        subcc           %g1, 64, %g1
        bne,pt          %XCC, 8b
@@ -211,31 +294,31 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
        ba,pt           %XCC, 60f
         add            %i1, %i4, %i1
 
-9:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3))
+9:     EX_LD(LOAD_TWIN(%i1 + %o4, %o2, %o3), NG_ret_i2_plus_g1)
        MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
        LOAD(prefetch, %i1 + %i3, #one_read)
 
-       EX_ST(STORE_INIT(%g3, %o0 + 0x00))
-       EX_ST(STORE_INIT(%o2, %o0 + 0x08))
+       EX_ST(STORE_INIT(%g3, %o0 + 0x00), NG_ret_i2_plus_g1)
+       EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
 
-       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3))
+       EX_LD(LOAD_TWIN(%i1 + %o5, %g2, %g3), NG_ret_i2_plus_g1_minus_16)
        MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%o3, %o0 + 0x10))
-       EX_ST(STORE_INIT(%g2, %o0 + 0x18))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%g2, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
 
-       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
        MIX_THREE_WORDS(%g3, %o2, %o3, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%g3, %o0 + 0x20))
-       EX_ST(STORE_INIT(%o2, %o0 + 0x28))
+       EX_ST(STORE_INIT(%g3, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+       EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
 
-       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3))
+       EX_LD(LOAD_TWIN(%i1 + %i3, %g2, %g3), NG_ret_i2_plus_g1_minus_48)
        add             %i1, 64, %i1
        MIX_THREE_WORDS(%o3, %g2, %g3, %i5, GLOBAL_SPARE, %o1)
 
-       EX_ST(STORE_INIT(%o3, %o0 + 0x30))
-       EX_ST(STORE_INIT(%g2, %o0 + 0x38))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+       EX_ST(STORE_INIT(%g2, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
 
        subcc           %g1, 64, %g1
        bne,pt          %XCC, 9b
@@ -249,25 +332,25 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
         * one twin load ahead, then add 8 back into source when
         * we finish the loop.
         */
-       EX_LD(LOAD_TWIN(%i1, %o4, %o5))
+       EX_LD(LOAD_TWIN(%i1, %o4, %o5), NG_ret_i2_plus_g1)
        mov     16, %o7
        mov     32, %g2
        mov     48, %g3
        mov     64, %o1
-1:     EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+1:     EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1)
        LOAD(prefetch, %i1 + %o1, #one_read)
-       EX_ST(STORE_INIT(%o5, %o0 + 0x00))      ! initializes cache line
-       EX_ST(STORE_INIT(%o2, %o0 + 0x08))
-       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
-       EX_ST(STORE_INIT(%o3, %o0 + 0x10))
-       EX_ST(STORE_INIT(%o4, %o0 + 0x18))
-       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
-       EX_ST(STORE_INIT(%o5, %o0 + 0x20))
-       EX_ST(STORE_INIT(%o2, %o0 + 0x28))
-       EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5))
+       EX_ST(STORE_INIT(%o5, %o0 + 0x00), NG_ret_i2_plus_g1)   ! initializes cache line
+       EX_ST(STORE_INIT(%o2, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
+       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%o3, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%o4, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
+       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
+       EX_ST(STORE_INIT(%o5, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+       EX_ST(STORE_INIT(%o2, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
+       EX_LD(LOAD_TWIN(%i1 + %o1, %o4, %o5), NG_ret_i2_plus_g1_minus_48)
        add             %i1, 64, %i1
-       EX_ST(STORE_INIT(%o3, %o0 + 0x30))
-       EX_ST(STORE_INIT(%o4, %o0 + 0x38))
+       EX_ST(STORE_INIT(%o3, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+       EX_ST(STORE_INIT(%o4, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
        subcc           %g1, 64, %g1
        bne,pt          %XCC, 1b
         add            %o0, 64, %o0
@@ -282,20 +365,20 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
        mov     32, %g2
        mov     48, %g3
        mov     64, %o1
-1:     EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5))
-       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3))
+1:     EX_LD(LOAD_TWIN(%i1 + %g0, %o4, %o5), NG_ret_i2_plus_g1)
+       EX_LD(LOAD_TWIN(%i1 + %o7, %o2, %o3), NG_ret_i2_plus_g1)
        LOAD(prefetch, %i1 + %o1, #one_read)
-       EX_ST(STORE_INIT(%o4, %o0 + 0x00))      ! initializes cache line
-       EX_ST(STORE_INIT(%o5, %o0 + 0x08))
-       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5))
-       EX_ST(STORE_INIT(%o2, %o0 + 0x10))
-       EX_ST(STORE_INIT(%o3, %o0 + 0x18))
-       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3))
+       EX_ST(STORE_INIT(%o4, %o0 + 0x00), NG_ret_i2_plus_g1)   ! initializes cache line
+       EX_ST(STORE_INIT(%o5, %o0 + 0x08), NG_ret_i2_plus_g1_minus_8)
+       EX_LD(LOAD_TWIN(%i1 + %g2, %o4, %o5), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%o2, %o0 + 0x10), NG_ret_i2_plus_g1_minus_16)
+       EX_ST(STORE_INIT(%o3, %o0 + 0x18), NG_ret_i2_plus_g1_minus_24)
+       EX_LD(LOAD_TWIN(%i1 + %g3, %o2, %o3), NG_ret_i2_plus_g1_minus_32)
        add     %i1, 64, %i1
-       EX_ST(STORE_INIT(%o4, %o0 + 0x20))
-       EX_ST(STORE_INIT(%o5, %o0 + 0x28))
-       EX_ST(STORE_INIT(%o2, %o0 + 0x30))
-       EX_ST(STORE_INIT(%o3, %o0 + 0x38))
+       EX_ST(STORE_INIT(%o4, %o0 + 0x20), NG_ret_i2_plus_g1_minus_32)
+       EX_ST(STORE_INIT(%o5, %o0 + 0x28), NG_ret_i2_plus_g1_minus_40)
+       EX_ST(STORE_INIT(%o2, %o0 + 0x30), NG_ret_i2_plus_g1_minus_48)
+       EX_ST(STORE_INIT(%o3, %o0 + 0x38), NG_ret_i2_plus_g1_minus_56)
        subcc   %g1, 64, %g1
        bne,pt  %XCC, 1b
         add    %o0, 64, %o0
@@ -321,28 +404,28 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
        andn            %i2, 0xf, %i4
        and             %i2, 0xf, %i2
 1:     subcc           %i4, 0x10, %i4
-       EX_LD(LOAD(ldx, %i1, %o4))
+       EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_i4)
        add             %i1, 0x08, %i1
-       EX_LD(LOAD(ldx, %i1, %g1))
+       EX_LD(LOAD(ldx, %i1, %g1), NG_ret_i2_plus_i4)
        sub             %i1, 0x08, %i1
-       EX_ST(STORE(stx, %o4, %i1 + %i3))
+       EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_i4)
        add             %i1, 0x8, %i1
-       EX_ST(STORE(stx, %g1, %i1 + %i3))
+       EX_ST(STORE(stx, %g1, %i1 + %i3), NG_ret_i2_plus_i4_minus_8)
        bgu,pt          %XCC, 1b
         add            %i1, 0x8, %i1
 73:    andcc           %i2, 0x8, %g0
        be,pt           %XCC, 1f
         nop
        sub             %i2, 0x8, %i2
-       EX_LD(LOAD(ldx, %i1, %o4))
-       EX_ST(STORE(stx, %o4, %i1 + %i3))
+       EX_LD(LOAD(ldx, %i1, %o4), NG_ret_i2_plus_8)
+       EX_ST(STORE(stx, %o4, %i1 + %i3), NG_ret_i2_plus_8)
        add             %i1, 0x8, %i1
 1:     andcc           %i2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
        sub             %i2, 0x4, %i2
-       EX_LD(LOAD(lduw, %i1, %i5))
-       EX_ST(STORE(stw, %i5, %i1 + %i3))
+       EX_LD(LOAD(lduw, %i1, %i5), NG_ret_i2_plus_4)
+       EX_ST(STORE(stw, %i5, %i1 + %i3), NG_ret_i2_plus_4)
        add             %i1, 0x4, %i1
 1:     cmp             %i2, 0
        be,pt           %XCC, 85f
@@ -358,8 +441,8 @@ FUNC_NAME:  /* %i0=dst, %i1=src, %i2=len */
        sub             %i2, %g1, %i2
 
 1:     subcc           %g1, 1, %g1
-       EX_LD(LOAD(ldub, %i1, %i5))
-       EX_ST(STORE(stb, %i5, %i1 + %i3))
+       EX_LD(LOAD(ldub, %i1, %i5), NG_ret_i2_plus_g1_plus_1)
+       EX_ST(STORE(stb, %i5, %i1 + %i3), NG_ret_i2_plus_g1_plus_1)
        bgu,pt          %icc, 1b
         add            %i1, 1, %i1
 
@@ -375,16 +458,16 @@ FUNC_NAME:        /* %i0=dst, %i1=src, %i2=len */
 
 8:     mov             64, %i3
        andn            %i1, 0x7, %i1
-       EX_LD(LOAD(ldx, %i1, %g2))
+       EX_LD(LOAD(ldx, %i1, %g2), NG_ret_i2)
        sub             %i3, %g1, %i3
        andn            %i2, 0x7, %i4
        sllx            %g2, %g1, %g2
 1:     add             %i1, 0x8, %i1
-       EX_LD(LOAD(ldx, %i1, %g3))
+       EX_LD(LOAD(ldx, %i1, %g3), NG_ret_i2_and_7_plus_i4)
        subcc           %i4, 0x8, %i4
        srlx            %g3, %i3, %i5
        or              %i5, %g2, %i5
-       EX_ST(STORE(stx, %i5, %o0))
+       EX_ST(STORE(stx, %i5, %o0), NG_ret_i2_and_7_plus_i4)
        add             %o0, 0x8, %o0
        bgu,pt          %icc, 1b
         sllx           %g3, %g1, %g2
@@ -404,8 +487,8 @@ FUNC_NAME:  /* %i0=dst, %i1=src, %i2=len */
 
 1:
        subcc           %i2, 4, %i2
-       EX_LD(LOAD(lduw, %i1, %g1))
-       EX_ST(STORE(stw, %g1, %i1 + %i3))
+       EX_LD(LOAD(lduw, %i1, %g1), NG_ret_i2_plus_4)
+       EX_ST(STORE(stw, %g1, %i1 + %i3), NG_ret_i2_plus_4)
        bgu,pt          %XCC, 1b
         add            %i1, 4, %i1
 
@@ -415,8 +498,8 @@ FUNC_NAME:  /* %i0=dst, %i1=src, %i2=len */
        .align          32
 90:
        subcc           %i2, 1, %i2
-       EX_LD(LOAD(ldub, %i1, %g1))
-       EX_ST(STORE(stb, %g1, %i1 + %i3))
+       EX_LD(LOAD(ldub, %i1, %g1), NG_ret_i2_plus_1)
+       EX_ST(STORE(stb, %g1, %i1 + %i3), NG_ret_i2_plus_1)
        bgu,pt          %XCC, 90b
         add            %i1, 1, %i1
        ret
index ecc5692..bb6ff73 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_LD_FP(x)            \
+#define EX_LD_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_fp;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index 9eea392..ed92ce7 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_ST_FP(x)            \
+#define EX_ST_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_fp;\
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
index 97e1b21..4f0d50b 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #include <asm/export.h>
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)    x
+#define EX_LD_FP(x,y)  x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
+#define EX_ST(x,y)     x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)    x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
+#define EX_ST_FP(x,y)  x
 #endif
 
 #ifndef LOAD
        faligndata              %f7, %f8, %f60;                 \
        faligndata              %f8, %f9, %f62;
 
-#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)   \
-       EX_LD_FP(LOAD_BLK(%src, %fdest));                               \
-       EX_ST_FP(STORE_BLK(%fsrc, %dest));                              \
-       add                     %src, 0x40, %src;               \
-       subcc                   %len, 0x40, %len;               \
-       be,pn                   %xcc, jmptgt;                   \
-        add                    %dest, 0x40, %dest;             \
-
-#define LOOP_CHUNK1(src, dest, len, branch_dest)               \
-       MAIN_LOOP_CHUNK(src, dest, f0,  f48, len, branch_dest)
-#define LOOP_CHUNK2(src, dest, len, branch_dest)               \
-       MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest)
-#define LOOP_CHUNK3(src, dest, len, branch_dest)               \
-       MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest)
+#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, jmptgt)                        \
+       EX_LD_FP(LOAD_BLK(%src, %fdest), U1_gs_80_fp);                  \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp);                 \
+       add                     %src, 0x40, %src;                       \
+       subcc                   %GLOBAL_SPARE, 0x40, %GLOBAL_SPARE;     \
+       be,pn                   %xcc, jmptgt;                           \
+        add                    %dest, 0x40, %dest;                     \
+
+#define LOOP_CHUNK1(src, dest, branch_dest)            \
+       MAIN_LOOP_CHUNK(src, dest, f0,  f48, branch_dest)
+#define LOOP_CHUNK2(src, dest, branch_dest)            \
+       MAIN_LOOP_CHUNK(src, dest, f16, f48, branch_dest)
+#define LOOP_CHUNK3(src, dest, branch_dest)            \
+       MAIN_LOOP_CHUNK(src, dest, f32, f48, branch_dest)
 
 #define DO_SYNC                        membar  #Sync;
 #define STORE_SYNC(dest, fsrc)                         \
-       EX_ST_FP(STORE_BLK(%fsrc, %dest));                      \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_80_fp); \
        add                     %dest, 0x40, %dest;     \
        DO_SYNC
 
 #define STORE_JUMP(dest, fsrc, target)                 \
-       EX_ST_FP(STORE_BLK(%fsrc, %dest));                      \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest), U1_gs_40_fp); \
        add                     %dest, 0x40, %dest;     \
        ba,pt                   %xcc, target;           \
         nop;
 
-#define FINISH_VISCHUNK(dest, f0, f1, left)    \
-       subcc                   %left, 8, %left;\
-       bl,pn                   %xcc, 95f;      \
-        faligndata             %f0, %f1, %f48; \
-       EX_ST_FP(STORE(std, %f48, %dest));              \
+#define FINISH_VISCHUNK(dest, f0, f1)                  \
+       subcc                   %g3, 8, %g3;            \
+       bl,pn                   %xcc, 95f;              \
+        faligndata             %f0, %f1, %f48;         \
+       EX_ST_FP(STORE(std, %f48, %dest), U1_g3_8_fp);  \
        add                     %dest, 8, %dest;
 
-#define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)       \
-       subcc                   %left, 8, %left;        \
-       bl,pn                   %xcc, 95f;              \
+#define UNEVEN_VISCHUNK_LAST(dest, f0, f1)     \
+       subcc                   %g3, 8, %g3;    \
+       bl,pn                   %xcc, 95f;      \
         fsrc2                  %f0, %f1;
 
-#define UNEVEN_VISCHUNK(dest, f0, f1, left)            \
-       UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)        \
+#define UNEVEN_VISCHUNK(dest, f0, f1)          \
+       UNEVEN_VISCHUNK_LAST(dest, f0, f1)      \
        ba,a,pt                 %xcc, 93f;
 
        .register       %g2,#scratch
        .register       %g3,#scratch
 
        .text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+ENTRY(U1_g1_1_fp)
+       VISExitHalf
+       add             %g1, 1, %g1
+       add             %g1, %g2, %g1
+       retl
+        add            %g1, %o2, %o0
+ENDPROC(U1_g1_1_fp)
+ENTRY(U1_g2_0_fp)
+       VISExitHalf
+       retl
+        add            %g2, %o2, %o0
+ENDPROC(U1_g2_0_fp)
+ENTRY(U1_g2_8_fp)
+       VISExitHalf
+       add             %g2, 8, %g2
+       retl
+        add            %g2, %o2, %o0
+ENDPROC(U1_g2_8_fp)
+ENTRY(U1_gs_0_fp)
+       VISExitHalf
+       add             %GLOBAL_SPARE, %g3, %o0
+       retl
+        add            %o0, %o2, %o0
+ENDPROC(U1_gs_0_fp)
+ENTRY(U1_gs_80_fp)
+       VISExitHalf
+       add             %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
+       add             %GLOBAL_SPARE, %g3, %o0
+       retl
+        add            %o0, %o2, %o0
+ENDPROC(U1_gs_80_fp)
+ENTRY(U1_gs_40_fp)
+       VISExitHalf
+       add             %GLOBAL_SPARE, 0x40, %GLOBAL_SPARE
+       add             %GLOBAL_SPARE, %g3, %o0
+       retl
+        add            %o0, %o2, %o0
+ENDPROC(U1_gs_40_fp)
+ENTRY(U1_g3_0_fp)
+       VISExitHalf
+       retl
+        add            %g3, %o2, %o0
+ENDPROC(U1_g3_0_fp)
+ENTRY(U1_g3_8_fp)
+       VISExitHalf
+       add             %g3, 8, %g3
+       retl
+        add            %g3, %o2, %o0
+ENDPROC(U1_g3_8_fp)
+ENTRY(U1_o2_0_fp)
+       VISExitHalf
+       retl
+        mov            %o2, %o0
+ENDPROC(U1_o2_0_fp)
+ENTRY(U1_o2_1_fp)
+       VISExitHalf
+       retl
+        add            %o2, 1, %o0
+ENDPROC(U1_o2_1_fp)
+ENTRY(U1_gs_0)
+       VISExitHalf
+       retl
+        add            %GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_0)
+ENTRY(U1_gs_8)
+       VISExitHalf
+       add             %GLOBAL_SPARE, %o2, %GLOBAL_SPARE
+       retl
+        add            %GLOBAL_SPARE, 0x8, %o0
+ENDPROC(U1_gs_8)
+ENTRY(U1_gs_10)
+       VISExitHalf
+       add             %GLOBAL_SPARE, %o2, %GLOBAL_SPARE
+       retl
+        add            %GLOBAL_SPARE, 0x10, %o0
+ENDPROC(U1_gs_10)
+ENTRY(U1_o2_0)
+       retl
+        mov            %o2, %o0
+ENDPROC(U1_o2_0)
+ENTRY(U1_o2_8)
+       retl
+        add            %o2, 8, %o0
+ENDPROC(U1_o2_8)
+ENTRY(U1_o2_4)
+       retl
+        add            %o2, 4, %o0
+ENDPROC(U1_o2_4)
+ENTRY(U1_o2_1)
+       retl
+        add            %o2, 1, %o0
+ENDPROC(U1_o2_1)
+ENTRY(U1_g1_0)
+       retl
+        add            %g1, %o2, %o0
+ENDPROC(U1_g1_0)
+ENTRY(U1_g1_1)
+       add             %g1, 1, %g1
+       retl
+        add            %g1, %o2, %o0
+ENDPROC(U1_g1_1)
+ENTRY(U1_gs_0_o2_adj)
+       and             %o2, 7, %o2
+       retl
+        add            %GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_0_o2_adj)
+ENTRY(U1_gs_8_o2_adj)
+       and             %o2, 7, %o2
+       add             %GLOBAL_SPARE, 8, %GLOBAL_SPARE
+       retl
+        add            %GLOBAL_SPARE, %o2, %o0
+ENDPROC(U1_gs_8_o2_adj)
+#endif
+
        .align          64
 
        .globl          FUNC_NAME
@@ -167,8 +280,8 @@ FUNC_NAME:          /* %o0=dst, %o1=src, %o2=len */
         and            %g2, 0x38, %g2
 
 1:     subcc           %g1, 0x1, %g1
-       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
-       EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
+       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U1_g1_1_fp)
+       EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE), U1_g1_1_fp)
        bgu,pt          %XCC, 1b
         add            %o1, 0x1, %o1
 
@@ -179,20 +292,20 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        be,pt           %icc, 3f
         alignaddr      %o1, %g0, %o1
 
-       EX_LD_FP(LOAD(ldd, %o1, %f4))
-1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
+       EX_LD_FP(LOAD(ldd, %o1, %f4), U1_g2_0_fp)
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U1_g2_0_fp)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f4, %f6, %f0
-       EX_ST_FP(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp)
        be,pn           %icc, 3f
         add            %o0, 0x8, %o0
 
-       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U1_g2_0_fp)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f6, %f4, %f0
-       EX_ST_FP(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0), U1_g2_8_fp)
        bne,pt          %icc, 1b
         add            %o0, 0x8, %o0
 
@@ -215,13 +328,13 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        add             %g1, %GLOBAL_SPARE, %g1
        subcc           %o2, %g3, %o2
 
-       EX_LD_FP(LOAD_BLK(%o1, %f0))
+       EX_LD_FP(LOAD_BLK(%o1, %f0), U1_gs_0_fp)
        add             %o1, 0x40, %o1
        add             %g1, %g3, %g1
-       EX_LD_FP(LOAD_BLK(%o1, %f16))
+       EX_LD_FP(LOAD_BLK(%o1, %f16), U1_gs_0_fp)
        add             %o1, 0x40, %o1
        sub             %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
-       EX_LD_FP(LOAD_BLK(%o1, %f32))
+       EX_LD_FP(LOAD_BLK(%o1, %f32), U1_gs_80_fp)
        add             %o1, 0x40, %o1
 
        /* There are 8 instances of the unrolled loop,
@@ -241,11 +354,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
 
        .align          64
 1:     FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f0, %f2, %f48
 1:     FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32)
@@ -262,11 +375,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 56f)
 
 1:     FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f2, %f4, %f48
 1:     FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34)
@@ -283,11 +396,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 57f)
 
 1:     FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f4, %f6, %f48
 1:     FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36)
@@ -304,11 +417,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 58f)
 
 1:     FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) 
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f6, %f8, %f48
 1:     FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38)
@@ -325,11 +438,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 59f)
 
 1:     FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f8, %f10, %f48
 1:     FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40)
@@ -346,11 +459,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 60f)
 
 1:     FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f10, %f12, %f48
 1:     FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42)
@@ -367,11 +480,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 61f)
 
 1:     FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f12, %f14, %f48
 1:     FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44)
@@ -388,11 +501,11 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        STORE_JUMP(o0, f48, 62f)
 
 1:     FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30)
-       LOOP_CHUNK1(o1, o0, GLOBAL_SPARE, 1f)
+       LOOP_CHUNK1(o1, o0, 1f)
        FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
-       LOOP_CHUNK2(o1, o0, GLOBAL_SPARE, 2f)
+       LOOP_CHUNK2(o1, o0, 2f)
        FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14)
-       LOOP_CHUNK3(o1, o0, GLOBAL_SPARE, 3f)
+       LOOP_CHUNK3(o1, o0, 3f)
        ba,pt           %xcc, 1b+4
         faligndata     %f14, %f16, %f48
 1:     FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
@@ -408,53 +521,53 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46)
        STORE_JUMP(o0, f48, 63f)
 
-40:    FINISH_VISCHUNK(o0, f0,  f2,  g3)
-41:    FINISH_VISCHUNK(o0, f2,  f4,  g3)
-42:    FINISH_VISCHUNK(o0, f4,  f6,  g3)
-43:    FINISH_VISCHUNK(o0, f6,  f8,  g3)
-44:    FINISH_VISCHUNK(o0, f8,  f10, g3)
-45:    FINISH_VISCHUNK(o0, f10, f12, g3)
-46:    FINISH_VISCHUNK(o0, f12, f14, g3)
-47:    UNEVEN_VISCHUNK(o0, f14, f0,  g3)
-48:    FINISH_VISCHUNK(o0, f16, f18, g3)
-49:    FINISH_VISCHUNK(o0, f18, f20, g3)
-50:    FINISH_VISCHUNK(o0, f20, f22, g3)
-51:    FINISH_VISCHUNK(o0, f22, f24, g3)
-52:    FINISH_VISCHUNK(o0, f24, f26, g3)
-53:    FINISH_VISCHUNK(o0, f26, f28, g3)
-54:    FINISH_VISCHUNK(o0, f28, f30, g3)
-55:    UNEVEN_VISCHUNK(o0, f30, f0,  g3)
-56:    FINISH_VISCHUNK(o0, f32, f34, g3)
-57:    FINISH_VISCHUNK(o0, f34, f36, g3)
-58:    FINISH_VISCHUNK(o0, f36, f38, g3)
-59:    FINISH_VISCHUNK(o0, f38, f40, g3)
-60:    FINISH_VISCHUNK(o0, f40, f42, g3)
-61:    FINISH_VISCHUNK(o0, f42, f44, g3)
-62:    FINISH_VISCHUNK(o0, f44, f46, g3)
-63:    UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
-
-93:    EX_LD_FP(LOAD(ldd, %o1, %f2))
+40:    FINISH_VISCHUNK(o0, f0,  f2)
+41:    FINISH_VISCHUNK(o0, f2,  f4)
+42:    FINISH_VISCHUNK(o0, f4,  f6)
+43:    FINISH_VISCHUNK(o0, f6,  f8)
+44:    FINISH_VISCHUNK(o0, f8,  f10)
+45:    FINISH_VISCHUNK(o0, f10, f12)
+46:    FINISH_VISCHUNK(o0, f12, f14)
+47:    UNEVEN_VISCHUNK(o0, f14, f0)
+48:    FINISH_VISCHUNK(o0, f16, f18)
+49:    FINISH_VISCHUNK(o0, f18, f20)
+50:    FINISH_VISCHUNK(o0, f20, f22)
+51:    FINISH_VISCHUNK(o0, f22, f24)
+52:    FINISH_VISCHUNK(o0, f24, f26)
+53:    FINISH_VISCHUNK(o0, f26, f28)
+54:    FINISH_VISCHUNK(o0, f28, f30)
+55:    UNEVEN_VISCHUNK(o0, f30, f0)
+56:    FINISH_VISCHUNK(o0, f32, f34)
+57:    FINISH_VISCHUNK(o0, f34, f36)
+58:    FINISH_VISCHUNK(o0, f36, f38)
+59:    FINISH_VISCHUNK(o0, f38, f40)
+60:    FINISH_VISCHUNK(o0, f40, f42)
+61:    FINISH_VISCHUNK(o0, f42, f44)
+62:    FINISH_VISCHUNK(o0, f44, f46)
+63:    UNEVEN_VISCHUNK_LAST(o0, f46, f0)
+
+93:    EX_LD_FP(LOAD(ldd, %o1, %f2), U1_g3_0_fp)
        add             %o1, 8, %o1
        subcc           %g3, 8, %g3
        faligndata      %f0, %f2, %f8
-       EX_ST_FP(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp)
        bl,pn           %xcc, 95f
         add            %o0, 8, %o0
-       EX_LD_FP(LOAD(ldd, %o1, %f0))
+       EX_LD_FP(LOAD(ldd, %o1, %f0), U1_g3_0_fp)
        add             %o1, 8, %o1
        subcc           %g3, 8, %g3
        faligndata      %f2, %f0, %f8
-       EX_ST_FP(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0), U1_g3_8_fp)
        bge,pt          %xcc, 93b
         add            %o0, 8, %o0
 
 95:    brz,pt          %o2, 2f
         mov            %g1, %o1
 
-1:     EX_LD_FP(LOAD(ldub, %o1, %o3))
+1:     EX_LD_FP(LOAD(ldub, %o1, %o3), U1_o2_0_fp)
        add             %o1, 1, %o1
        subcc           %o2, 1, %o2
-       EX_ST_FP(STORE(stb, %o3, %o0))
+       EX_ST_FP(STORE(stb, %o3, %o0), U1_o2_1_fp)
        bne,pt          %xcc, 1b
         add            %o0, 1, %o0
 
@@ -470,27 +583,27 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
 
 72:    andn            %o2, 0xf, %GLOBAL_SPARE
        and             %o2, 0xf, %o2
-1:     EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
-       EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+1:     EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U1_gs_0)
+       EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U1_gs_0)
        subcc           %GLOBAL_SPARE, 0x10, %GLOBAL_SPARE
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       EX_ST(STORE(stx, %o5, %o1 + %o3), U1_gs_10)
        add             %o1, 0x8, %o1
-       EX_ST(STORE(stx, %g1, %o1 + %o3))
+       EX_ST(STORE(stx, %g1, %o1 + %o3), U1_gs_8)
        bgu,pt          %XCC, 1b
         add            %o1, 0x8, %o1
 73:    andcc           %o2, 0x8, %g0
        be,pt           %XCC, 1f
         nop
-       EX_LD(LOAD(ldx, %o1, %o5))
+       EX_LD(LOAD(ldx, %o1, %o5), U1_o2_0)
        sub             %o2, 0x8, %o2
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       EX_ST(STORE(stx, %o5, %o1 + %o3), U1_o2_8)
        add             %o1, 0x8, %o1
 1:     andcc           %o2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
-       EX_LD(LOAD(lduw, %o1, %o5))
+       EX_LD(LOAD(lduw, %o1, %o5), U1_o2_0)
        sub             %o2, 0x4, %o2
-       EX_ST(STORE(stw, %o5, %o1 + %o3))
+       EX_ST(STORE(stw, %o5, %o1 + %o3), U1_o2_4)
        add             %o1, 0x4, %o1
 1:     cmp             %o2, 0
        be,pt           %XCC, 85f
@@ -504,9 +617,9 @@ FUNC_NAME:          /* %o0=dst, %o1=src, %o2=len */
         sub            %g0, %g1, %g1
        sub             %o2, %g1, %o2
 
-1:     EX_LD(LOAD(ldub, %o1, %o5))
+1:     EX_LD(LOAD(ldub, %o1, %o5), U1_g1_0)
        subcc           %g1, 1, %g1
-       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       EX_ST(STORE(stb, %o5, %o1 + %o3), U1_g1_1)
        bgu,pt          %icc, 1b
         add            %o1, 1, %o1
 
@@ -522,16 +635,16 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
 
 8:     mov             64, %o3
        andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1, %g2))
+       EX_LD(LOAD(ldx, %o1, %g2), U1_o2_0)
        sub             %o3, %g1, %o3
        andn            %o2, 0x7, %GLOBAL_SPARE
        sllx            %g2, %g1, %g2
-1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U1_gs_0_o2_adj)
        subcc           %GLOBAL_SPARE, 0x8, %GLOBAL_SPARE
        add             %o1, 0x8, %o1
        srlx            %g3, %o3, %o5
        or              %o5, %g2, %o5
-       EX_ST(STORE(stx, %o5, %o0))
+       EX_ST(STORE(stx, %o5, %o0), U1_gs_8_o2_adj)
        add             %o0, 0x8, %o0
        bgu,pt          %icc, 1b
         sllx           %g3, %g1, %g2
@@ -549,9 +662,9 @@ FUNC_NAME:          /* %o0=dst, %o1=src, %o2=len */
        bne,pn          %XCC, 90f
         sub            %o0, %o1, %o3
 
-1:     EX_LD(LOAD(lduw, %o1, %g1))
+1:     EX_LD(LOAD(lduw, %o1, %g1), U1_o2_0)
        subcc           %o2, 4, %o2
-       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       EX_ST(STORE(stw, %g1, %o1 + %o3), U1_o2_4)
        bgu,pt          %XCC, 1b
         add            %o1, 4, %o1
 
@@ -559,9 +672,9 @@ FUNC_NAME:          /* %o0=dst, %o1=src, %o2=len */
         mov            EX_RETVAL(%o4), %o0
 
        .align          32
-90:    EX_LD(LOAD(ldub, %o1, %g1))
+90:    EX_LD(LOAD(ldub, %o1, %g1), U1_o2_0)
        subcc           %o2, 1, %o2
-       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       EX_ST(STORE(stb, %g1, %o1 + %o3), U1_o2_1)
        bgu,pt          %XCC, 90b
         add            %o1, 1, %o1
        retl
index 88ad73d..db73010 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_LD(x)               \
+#define EX_LD(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_LD_FP(x)            \
+#define EX_LD_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index 845139d..c4ee858 100644 (file)
@@ -3,19 +3,19 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#define EX_ST(x)               \
+#define EX_ST(x,y)             \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, y;           \
        .text;                  \
        .align 4;
 
-#define EX_ST_FP(x)            \
+#define EX_ST_FP(x,y)          \
 98:    x;                      \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one_fp;\
+       .word 98b, y##_fp;      \
        .text;                  \
        .align 4;
 
index 491ee69..54f9870 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #ifdef __KERNEL__
+#include <linux/linkage.h>
 #include <asm/visasm.h>
 #include <asm/asi.h>
 #define GLOBAL_SPARE   %g7
 #endif
 
 #ifndef EX_LD
-#define EX_LD(x)       x
+#define EX_LD(x,y)     x
 #endif
 #ifndef EX_LD_FP
-#define EX_LD_FP(x)    x
+#define EX_LD_FP(x,y)  x
 #endif
 
 #ifndef EX_ST
-#define EX_ST(x)       x
+#define EX_ST(x,y)     x
 #endif
 #ifndef EX_ST_FP
-#define EX_ST_FP(x)    x
-#endif
-
-#ifndef EX_RETVAL
-#define EX_RETVAL(x)   x
+#define EX_ST_FP(x,y)  x
 #endif
 
 #ifndef LOAD
         */
 
        .text
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+__restore_fp:
+       VISExitHalf
+       retl
+        nop
+ENTRY(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
+       add     %g1, 1, %g1
+       add     %g2, %g1, %g2
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_plus_g1_plus_1_fp)
+ENTRY(U3_retl_o2_plus_g2_fp)
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_fp)
+ENTRY(U3_retl_o2_plus_g2_plus_8_fp)
+       add     %g2, 8, %g2
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %g2, %o0
+ENDPROC(U3_retl_o2_plus_g2_plus_8_fp)
+ENTRY(U3_retl_o2)
+       retl
+        mov    %o2, %o0
+ENDPROC(U3_retl_o2)
+ENTRY(U3_retl_o2_plus_1)
+       retl
+        add    %o2, 1, %o0
+ENDPROC(U3_retl_o2_plus_1)
+ENTRY(U3_retl_o2_plus_4)
+       retl
+        add    %o2, 4, %o0
+ENDPROC(U3_retl_o2_plus_4)
+ENTRY(U3_retl_o2_plus_8)
+       retl
+        add    %o2, 8, %o0
+ENDPROC(U3_retl_o2_plus_8)
+ENTRY(U3_retl_o2_plus_g1_plus_1)
+       add     %g1, 1, %g1
+       retl
+        add    %o2, %g1, %o0
+ENDPROC(U3_retl_o2_plus_g1_plus_1)
+ENTRY(U3_retl_o2_fp)
+       ba,pt   %xcc, __restore_fp
+        mov    %o2, %o0
+ENDPROC(U3_retl_o2_fp)
+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
+       sll     %o3, 6, %o3
+       add     %o3, 0x80, %o3
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %o3, %o0
+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x80_fp)
+ENTRY(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
+       sll     %o3, 6, %o3
+       add     %o3, 0x40, %o3
+       ba,pt   %xcc, __restore_fp
+        add    %o2, %o3, %o0
+ENDPROC(U3_retl_o2_plus_o3_sll_6_plus_0x40_fp)
+ENTRY(U3_retl_o2_plus_GS_plus_0x10)
+       add     GLOBAL_SPARE, 0x10, GLOBAL_SPARE
+       retl
+        add    %o2, GLOBAL_SPARE, %o0
+ENDPROC(U3_retl_o2_plus_GS_plus_0x10)
+ENTRY(U3_retl_o2_plus_GS_plus_0x08)
+       add     GLOBAL_SPARE, 0x08, GLOBAL_SPARE
+       retl
+        add    %o2, GLOBAL_SPARE, %o0
+ENDPROC(U3_retl_o2_plus_GS_plus_0x08)
+ENTRY(U3_retl_o2_and_7_plus_GS)
+       and     %o2, 7, %o2
+       retl
+        add    %o2, GLOBAL_SPARE, %o2
+ENDPROC(U3_retl_o2_and_7_plus_GS)
+ENTRY(U3_retl_o2_and_7_plus_GS_plus_8)
+       add     GLOBAL_SPARE, 8, GLOBAL_SPARE
+       and     %o2, 7, %o2
+       retl
+        add    %o2, GLOBAL_SPARE, %o2
+ENDPROC(U3_retl_o2_and_7_plus_GS_plus_8)
+#endif
+
        .align          64
 
        /* The cheetah's flexible spine, oversized liver, enlarged heart,
@@ -126,8 +204,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
         and            %g2, 0x38, %g2
 
 1:     subcc           %g1, 0x1, %g1
-       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
-       EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
+       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3), U3_retl_o2_plus_g2_plus_g1_plus_1)
+       EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE), U3_retl_o2_plus_g2_plus_g1_plus_1)
        bgu,pt          %XCC, 1b
         add            %o1, 0x1, %o1
 
@@ -138,20 +216,20 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        be,pt           %icc, 3f
         alignaddr      %o1, %g0, %o1
 
-       EX_LD_FP(LOAD(ldd, %o1, %f4))
-1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
+       EX_LD_FP(LOAD(ldd, %o1, %f4), U3_retl_o2_plus_g2)
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6), U3_retl_o2_plus_g2)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f4, %f6, %f0
-       EX_ST_FP(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0), U3_retl_o2_plus_g2_plus_8)
        be,pn           %icc, 3f
         add            %o0, 0x8, %o0
 
-       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4), U3_retl_o2_plus_g2)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f6, %f4, %f2
-       EX_ST_FP(STORE(std, %f2, %o0))
+       EX_ST_FP(STORE(std, %f2, %o0), U3_retl_o2_plus_g2_plus_8)
        bne,pt          %icc, 1b
         add            %o0, 0x8, %o0
 
@@ -161,25 +239,25 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        LOAD(prefetch, %o1 + 0x080, #one_read)
        LOAD(prefetch, %o1 + 0x0c0, #one_read)
        LOAD(prefetch, %o1 + 0x100, #one_read)
-       EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0), U3_retl_o2)
        LOAD(prefetch, %o1 + 0x140, #one_read)
-       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2)
        LOAD(prefetch, %o1 + 0x180, #one_read)
-       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2)
        LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f0, %f2, %f16
-       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2)
        faligndata      %f2, %f4, %f18
-       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2)
        faligndata      %f4, %f6, %f20
-       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2)
        faligndata      %f6, %f8, %f22
 
-       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2)
        faligndata      %f8, %f10, %f24
-       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2)
        faligndata      %f10, %f12, %f26
-       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2)
 
        subcc           GLOBAL_SPARE, 0x80, GLOBAL_SPARE
        add             %o1, 0x40, %o1
@@ -190,26 +268,26 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        .align          64
 1:
-       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
        faligndata      %f12, %f14, %f28
-       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
        faligndata      %f14, %f0, %f30
-       EX_ST_FP(STORE_BLK(%f16, %o0))
-       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f0, %f2, %f16
        add             %o0, 0x40, %o0
 
-       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f2, %f4, %f18
-       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f4, %f6, %f20
-       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        subcc           %o3, 0x01, %o3
        faligndata      %f6, %f8, %f22
-       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x80)
 
        faligndata      %f8, %f10, %f24
-       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
        LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f10, %f12, %f26
        bg,pt           %XCC, 1b
@@ -217,29 +295,29 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        /* Finally we copy the last full 64-byte block. */
 2:
-       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2), U3_retl_o2_plus_o3_sll_6_plus_0x80)
        faligndata      %f12, %f14, %f28
-       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4), U3_retl_o2_plus_o3_sll_6_plus_0x80)
        faligndata      %f14, %f0, %f30
-       EX_ST_FP(STORE_BLK(%f16, %o0))
-       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x80)
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f0, %f2, %f16
-       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f2, %f4, %f18
-       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f4, %f6, %f20
-       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f6, %f8, %f22
-       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        faligndata      %f8, %f10, %f24
        cmp             %g1, 0
        be,pt           %XCC, 1f
         add            %o0, 0x40, %o0
-       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
 1:     faligndata      %f10, %f12, %f26
        faligndata      %f12, %f14, %f28
        faligndata      %f14, %f0, %f30
-       EX_ST_FP(STORE_BLK(%f16, %o0))
+       EX_ST_FP(STORE_BLK(%f16, %o0), U3_retl_o2_plus_o3_sll_6_plus_0x40)
        add             %o0, 0x40, %o0
        add             %o1, 0x40, %o1
        membar          #Sync
@@ -259,20 +337,20 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        sub             %o2, %g2, %o2
        be,a,pt         %XCC, 1f
-        EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0))
+        EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0), U3_retl_o2_plus_g2)
 
-1:     EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2))
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2), U3_retl_o2_plus_g2)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f0, %f2, %f8
-       EX_ST_FP(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
        be,pn           %XCC, 2f
         add            %o0, 0x8, %o0
-       EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0), U3_retl_o2_plus_g2)
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f2, %f0, %f8
-       EX_ST_FP(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0), U3_retl_o2_plus_g2_plus_8)
        bne,pn          %XCC, 1b
         add            %o0, 0x8, %o0
 
@@ -292,30 +370,33 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         andcc          %o2, 0x8, %g0
        be,pt           %icc, 1f
         nop
-       EX_LD(LOAD(ldx, %o1, %o5))
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2)
+       EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2)
        add             %o1, 0x8, %o1
+       sub             %o2, 8, %o2
 
 1:     andcc           %o2, 0x4, %g0
        be,pt           %icc, 1f
         nop
-       EX_LD(LOAD(lduw, %o1, %o5))
-       EX_ST(STORE(stw, %o5, %o1 + %o3))
+       EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2)
+       EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2)
        add             %o1, 0x4, %o1
+       sub             %o2, 4, %o2
 
 1:     andcc           %o2, 0x2, %g0
        be,pt           %icc, 1f
         nop
-       EX_LD(LOAD(lduh, %o1, %o5))
-       EX_ST(STORE(sth, %o5, %o1 + %o3))
+       EX_LD(LOAD(lduh, %o1, %o5), U3_retl_o2)
+       EX_ST(STORE(sth, %o5, %o1 + %o3), U3_retl_o2)
        add             %o1, 0x2, %o1
+       sub             %o2, 2, %o2
 
 1:     andcc           %o2, 0x1, %g0
        be,pt           %icc, 85f
         nop
-       EX_LD(LOAD(ldub, %o1, %o5))
+       EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2)
        ba,pt           %xcc, 85f
-        EX_ST(STORE(stb, %o5, %o1 + %o3))
+        EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2)
 
        .align          64
 70: /* 16 < len <= 64 */
@@ -326,26 +407,26 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        andn            %o2, 0xf, GLOBAL_SPARE
        and             %o2, 0xf, %o2
 1:     subcc           GLOBAL_SPARE, 0x10, GLOBAL_SPARE
-       EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
-       EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       EX_LD(LOAD(ldx, %o1 + 0x00, %o5), U3_retl_o2_plus_GS_plus_0x10)
+       EX_LD(LOAD(ldx, %o1 + 0x08, %g1), U3_retl_o2_plus_GS_plus_0x10)
+       EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x10)
        add             %o1, 0x8, %o1
-       EX_ST(STORE(stx, %g1, %o1 + %o3))
+       EX_ST(STORE(stx, %g1, %o1 + %o3), U3_retl_o2_plus_GS_plus_0x08)
        bgu,pt          %XCC, 1b
         add            %o1, 0x8, %o1
 73:    andcc           %o2, 0x8, %g0
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x8, %o2
-       EX_LD(LOAD(ldx, %o1, %o5))
-       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       EX_LD(LOAD(ldx, %o1, %o5), U3_retl_o2_plus_8)
+       EX_ST(STORE(stx, %o5, %o1 + %o3), U3_retl_o2_plus_8)
        add             %o1, 0x8, %o1
 1:     andcc           %o2, 0x4, %g0
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x4, %o2
-       EX_LD(LOAD(lduw, %o1, %o5))
-       EX_ST(STORE(stw, %o5, %o1 + %o3))
+       EX_LD(LOAD(lduw, %o1, %o5), U3_retl_o2_plus_4)
+       EX_ST(STORE(stw, %o5, %o1 + %o3), U3_retl_o2_plus_4)
        add             %o1, 0x4, %o1
 1:     cmp             %o2, 0
        be,pt           %XCC, 85f
@@ -361,8 +442,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        sub             %o2, %g1, %o2
 
 1:     subcc           %g1, 1, %g1
-       EX_LD(LOAD(ldub, %o1, %o5))
-       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       EX_LD(LOAD(ldub, %o1, %o5), U3_retl_o2_plus_g1_plus_1)
+       EX_ST(STORE(stb, %o5, %o1 + %o3), U3_retl_o2_plus_g1_plus_1)
        bgu,pt          %icc, 1b
         add            %o1, 1, %o1
 
@@ -378,16 +459,16 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 8:     mov             64, %o3
        andn            %o1, 0x7, %o1
-       EX_LD(LOAD(ldx, %o1, %g2))
+       EX_LD(LOAD(ldx, %o1, %g2), U3_retl_o2)
        sub             %o3, %g1, %o3
        andn            %o2, 0x7, GLOBAL_SPARE
        sllx            %g2, %g1, %g2
-1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+1:     EX_LD(LOAD(ldx, %o1 + 0x8, %g3), U3_retl_o2_and_7_plus_GS)
        subcc           GLOBAL_SPARE, 0x8, GLOBAL_SPARE
        add             %o1, 0x8, %o1
        srlx            %g3, %o3, %o5
        or              %o5, %g2, %o5
-       EX_ST(STORE(stx, %o5, %o0))
+       EX_ST(STORE(stx, %o5, %o0), U3_retl_o2_and_7_plus_GS_plus_8)
        add             %o0, 0x8, %o0
        bgu,pt          %icc, 1b
         sllx           %g3, %g1, %g2
@@ -407,8 +488,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
 
 1:
        subcc           %o2, 4, %o2
-       EX_LD(LOAD(lduw, %o1, %g1))
-       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       EX_LD(LOAD(lduw, %o1, %g1), U3_retl_o2_plus_4)
+       EX_ST(STORE(stw, %g1, %o1 + %o3), U3_retl_o2_plus_4)
        bgu,pt          %XCC, 1b
         add            %o1, 4, %o1
 
@@ -418,8 +499,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
        .align          32
 90:
        subcc           %o2, 1, %o2
-       EX_LD(LOAD(ldub, %o1, %g1))
-       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       EX_LD(LOAD(ldub, %o1, %g1), U3_retl_o2_plus_1)
+       EX_ST(STORE(stb, %g1, %o1 + %o3), U3_retl_o2_plus_1)
        bgu,pt          %XCC, 90b
         add            %o1, 1, %o1
        retl
index 482de09..0252b21 100644 (file)
@@ -9,18 +9,33 @@
 
 #define XCC xcc
 
-#define EX(x,y)                        \
+#define EX(x,y,z)              \
 98:    x,y;                    \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_one;  \
+       .word 98b, z;           \
        .text;                  \
        .align 4;
 
+#define EX_O4(x,y) EX(x,y,__retl_o4_plus_8)
+#define EX_O2_4(x,y) EX(x,y,__retl_o2_plus_4)
+#define EX_O2_1(x,y) EX(x,y,__retl_o2_plus_1)
+
        .register       %g2,#scratch
        .register       %g3,#scratch
 
        .text
+__retl_o4_plus_8:
+       add     %o4, %o2, %o4
+       retl
+        add    %o4, 8, %o0
+__retl_o2_plus_4:
+       retl
+        add    %o2, 4, %o0
+__retl_o2_plus_1:
+       retl
+        add    %o2, 1, %o0
+
        .align  32
 
        /* Don't try to get too fancy here, just nice and
@@ -45,8 +60,8 @@ ENTRY(___copy_in_user)        /* %o0=dst, %o1=src, %o2=len */
        andn            %o2, 0x7, %o4
        and             %o2, 0x7, %o2
 1:     subcc           %o4, 0x8, %o4
-       EX(ldxa [%o1] %asi, %o5)
-       EX(stxa %o5, [%o0] %asi)
+       EX_O4(ldxa [%o1] %asi, %o5)
+       EX_O4(stxa %o5, [%o0] %asi)
        add             %o1, 0x8, %o1
        bgu,pt          %XCC, 1b
         add            %o0, 0x8, %o0
@@ -54,8 +69,8 @@ ENTRY(___copy_in_user)        /* %o0=dst, %o1=src, %o2=len */
        be,pt           %XCC, 1f
         nop
        sub             %o2, 0x4, %o2
-       EX(lduwa [%o1] %asi, %o5)
-       EX(stwa %o5, [%o0] %asi)
+       EX_O2_4(lduwa [%o1] %asi, %o5)
+       EX_O2_4(stwa %o5, [%o0] %asi)
        add             %o1, 0x4, %o1
        add             %o0, 0x4, %o0
 1:     cmp             %o2, 0
@@ -71,8 +86,8 @@ ENTRY(___copy_in_user)        /* %o0=dst, %o1=src, %o2=len */
 
 82:
        subcc           %o2, 4, %o2
-       EX(lduwa [%o1] %asi, %g1)
-       EX(stwa %g1, [%o0] %asi)
+       EX_O2_4(lduwa [%o1] %asi, %g1)
+       EX_O2_4(stwa %g1, [%o0] %asi)
        add             %o1, 4, %o1
        bgu,pt          %XCC, 82b
         add            %o0, 4, %o0
@@ -83,8 +98,8 @@ ENTRY(___copy_in_user)        /* %o0=dst, %o1=src, %o2=len */
        .align  32
 90:
        subcc           %o2, 1, %o2
-       EX(lduba [%o1] %asi, %g1)
-       EX(stba %g1, [%o0] %asi)
+       EX_O2_1(lduba [%o1] %asi, %g1)
+       EX_O2_1(stba %g1, [%o0] %asi)
        add             %o1, 1, %o1
        bgu,pt          %XCC, 90b
         add            %o0, 1, %o0
diff --git a/arch/sparc/lib/user_fixup.c b/arch/sparc/lib/user_fixup.c
deleted file mode 100644 (file)
index ac96ae2..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* user_fixup.c: Fix up user copy faults.
- *
- * Copyright (C) 2004 David S. Miller <davem@redhat.com>
- */
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-
-/* Calculating the exact fault address when using
- * block loads and stores can be very complicated.
- *
- * Instead of trying to be clever and handling all
- * of the cases, just fix things up simply here.
- */
-
-static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
-{
-       unsigned long fault_addr = current_thread_info()->fault_address;
-       unsigned long end = start + size;
-
-       if (fault_addr < start || fault_addr >= end) {
-               *offset = 0;
-       } else {
-               *offset = fault_addr - start;
-               size = end - fault_addr;
-       }
-       return size;
-}
-
-unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
-{
-       unsigned long offset;
-
-       size = compute_size((unsigned long) from, size, &offset);
-       if (likely(size))
-               memset(to + offset, 0, size);
-
-       return size;
-}
-EXPORT_SYMBOL(copy_from_user_fixup);
-
-unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
-{
-       unsigned long offset;
-
-       return compute_size((unsigned long) to, size, &offset);
-}
-EXPORT_SYMBOL(copy_to_user_fixup);
-
-unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
-{
-       unsigned long fault_addr = current_thread_info()->fault_address;
-       unsigned long start = (unsigned long) to;
-       unsigned long end = start + size;
-
-       if (fault_addr >= start && fault_addr < end)
-               return end - fault_addr;
-
-       start = (unsigned long) from;
-       end = start + size;
-       if (fault_addr >= start && fault_addr < end)
-               return end - fault_addr;
-
-       return size;
-}
-EXPORT_SYMBOL(copy_in_user_fixup);
index 4e06750..cd0e32b 100644 (file)
@@ -238,7 +238,8 @@ slow:
                pages += nr;
 
                ret = get_user_pages_unlocked(start,
-                       (end - start) >> PAGE_SHIFT, write, 0, pages);
+                       (end - start) >> PAGE_SHIFT, pages,
+                       write ? FOLL_WRITE : 0);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index f2b7711..e20fbba 100644 (file)
@@ -27,6 +27,20 @@ static inline int tag_compare(unsigned long tag, unsigned long vaddr)
        return (tag == (vaddr >> 22));
 }
 
+static void flush_tsb_kernel_range_scan(unsigned long start, unsigned long end)
+{
+       unsigned long idx;
+
+       for (idx = 0; idx < KERNEL_TSB_NENTRIES; idx++) {
+               struct tsb *ent = &swapper_tsb[idx];
+               unsigned long match = idx << 13;
+
+               match |= (ent->tag << 22);
+               if (match >= start && match < end)
+                       ent->tag = (1UL << TSB_TAG_INVALID_BIT);
+       }
+}
+
 /* TSB flushes need only occur on the processor initiating the address
  * space modification, not on each cpu the address space has run on.
  * Only the TLB flush needs that treatment.
@@ -36,6 +50,9 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end)
 {
        unsigned long v;
 
+       if ((end - start) >> PAGE_SHIFT >= 2 * KERNEL_TSB_NENTRIES)
+               return flush_tsb_kernel_range_scan(start, end);
+
        for (v = start; v < end; v += PAGE_SIZE) {
                unsigned long hash = tsb_hash(v, PAGE_SHIFT,
                                              KERNEL_TSB_NENTRIES);
index b4f4733..5d2fd6c 100644 (file)
@@ -30,7 +30,7 @@
        .text
        .align          32
        .globl          __flush_tlb_mm
-__flush_tlb_mm:                /* 18 insns */
+__flush_tlb_mm:                /* 19 insns */
        /* %o0=(ctx & TAG_CONTEXT_BITS), %o1=SECONDARY_CONTEXT */
        ldxa            [%o1] ASI_DMMU, %g2
        cmp             %g2, %o0
@@ -81,7 +81,7 @@ __flush_tlb_page:     /* 22 insns */
 
        .align          32
        .globl          __flush_tlb_pending
-__flush_tlb_pending:   /* 26 insns */
+__flush_tlb_pending:   /* 27 insns */
        /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
        rdpr            %pstate, %g7
        sllx            %o1, 3, %o1
@@ -113,12 +113,14 @@ __flush_tlb_pending:      /* 26 insns */
 
        .align          32
        .globl          __flush_tlb_kernel_range
-__flush_tlb_kernel_range:      /* 16 insns */
+__flush_tlb_kernel_range:      /* 31 insns */
        /* %o0=start, %o1=end */
        cmp             %o0, %o1
        be,pn           %xcc, 2f
+        sub            %o1, %o0, %o3
+       srlx            %o3, 18, %o4
+       brnz,pn         %o4, __spitfire_flush_tlb_kernel_range_slow
         sethi          %hi(PAGE_SIZE), %o4
-       sub             %o1, %o0, %o3
        sub             %o3, %o4, %o3
        or              %o0, 0x20, %o0          ! Nucleus
 1:     stxa            %g0, [%o0 + %o3] ASI_DMMU_DEMAP
@@ -131,6 +133,41 @@ __flush_tlb_kernel_range:  /* 16 insns */
        retl
         nop
        nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+
+__spitfire_flush_tlb_kernel_range_slow:
+       mov             63 * 8, %o4
+1:     ldxa            [%o4] ASI_ITLB_DATA_ACCESS, %o3
+       andcc           %o3, 0x40, %g0                  /* _PAGE_L_4U */
+       bne,pn          %xcc, 2f
+        mov            TLB_TAG_ACCESS, %o3
+       stxa            %g0, [%o3] ASI_IMMU
+       stxa            %g0, [%o4] ASI_ITLB_DATA_ACCESS
+       membar          #Sync
+2:     ldxa            [%o4] ASI_DTLB_DATA_ACCESS, %o3
+       andcc           %o3, 0x40, %g0
+       bne,pn          %xcc, 2f
+        mov            TLB_TAG_ACCESS, %o3
+       stxa            %g0, [%o3] ASI_DMMU
+       stxa            %g0, [%o4] ASI_DTLB_DATA_ACCESS
+       membar          #Sync
+2:     sub             %o4, 8, %o4
+       brgez,pt        %o4, 1b
+        nop
+       retl
+        nop
 
 __spitfire_flush_tlb_mm_slow:
        rdpr            %pstate, %g1
@@ -285,6 +322,40 @@ __cheetah_flush_tlb_pending:       /* 27 insns */
        retl
         wrpr           %g7, 0x0, %pstate
 
+__cheetah_flush_tlb_kernel_range:      /* 31 insns */
+       /* %o0=start, %o1=end */
+       cmp             %o0, %o1
+       be,pn           %xcc, 2f
+        sub            %o1, %o0, %o3
+       srlx            %o3, 18, %o4
+       brnz,pn         %o4, 3f
+        sethi          %hi(PAGE_SIZE), %o4
+       sub             %o3, %o4, %o3
+       or              %o0, 0x20, %o0          ! Nucleus
+1:     stxa            %g0, [%o0 + %o3] ASI_DMMU_DEMAP
+       stxa            %g0, [%o0 + %o3] ASI_IMMU_DEMAP
+       membar          #Sync
+       brnz,pt         %o3, 1b
+        sub            %o3, %o4, %o3
+2:     sethi           %hi(KERNBASE), %o3
+       flush           %o3
+       retl
+        nop
+3:     mov             0x80, %o4
+       stxa            %g0, [%o4] ASI_DMMU_DEMAP
+       membar          #Sync
+       stxa            %g0, [%o4] ASI_IMMU_DEMAP
+       membar          #Sync
+       retl
+        nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+
 #ifdef DCACHE_ALIASING_POSSIBLE
 __cheetah_flush_dcache_page: /* 11 insns */
        sethi           %hi(PAGE_OFFSET), %g1
@@ -309,19 +380,28 @@ __hypervisor_tlb_tl0_error:
        ret
         restore
 
-__hypervisor_flush_tlb_mm: /* 10 insns */
+__hypervisor_flush_tlb_mm: /* 19 insns */
        mov             %o0, %o2        /* ARG2: mmu context */
        mov             0, %o0          /* ARG0: CPU lists unimplemented */
        mov             0, %o1          /* ARG1: CPU lists unimplemented */
        mov             HV_MMU_ALL, %o3 /* ARG3: flags */
        mov             HV_FAST_MMU_DEMAP_CTX, %o5
        ta              HV_FAST_TRAP
-       brnz,pn         %o0, __hypervisor_tlb_tl0_error
+       brnz,pn         %o0, 1f
         mov            HV_FAST_MMU_DEMAP_CTX, %o1
        retl
         nop
+1:     sethi           %hi(__hypervisor_tlb_tl0_error), %o5
+       jmpl            %o5 + %lo(__hypervisor_tlb_tl0_error), %g0
+        nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
 
-__hypervisor_flush_tlb_page: /* 11 insns */
+__hypervisor_flush_tlb_page: /* 22 insns */
        /* %o0 = context, %o1 = vaddr */
        mov             %o0, %g2
        mov             %o1, %o0              /* ARG0: vaddr + IMMU-bit */
@@ -330,12 +410,23 @@ __hypervisor_flush_tlb_page: /* 11 insns */
        srlx            %o0, PAGE_SHIFT, %o0
        sllx            %o0, PAGE_SHIFT, %o0
        ta              HV_MMU_UNMAP_ADDR_TRAP
-       brnz,pn         %o0, __hypervisor_tlb_tl0_error
+       brnz,pn         %o0, 1f
         mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
        retl
         nop
+1:     sethi           %hi(__hypervisor_tlb_tl0_error), %o2
+       jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+        nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
 
-__hypervisor_flush_tlb_pending: /* 16 insns */
+__hypervisor_flush_tlb_pending: /* 27 insns */
        /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
        sllx            %o1, 3, %g1
        mov             %o2, %g2
@@ -347,31 +438,57 @@ __hypervisor_flush_tlb_pending: /* 16 insns */
        srlx            %o0, PAGE_SHIFT, %o0
        sllx            %o0, PAGE_SHIFT, %o0
        ta              HV_MMU_UNMAP_ADDR_TRAP
-       brnz,pn         %o0, __hypervisor_tlb_tl0_error
+       brnz,pn         %o0, 1f
         mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
        brnz,pt         %g1, 1b
         nop
        retl
         nop
+1:     sethi           %hi(__hypervisor_tlb_tl0_error), %o2
+       jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+        nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
 
-__hypervisor_flush_tlb_kernel_range: /* 16 insns */
+__hypervisor_flush_tlb_kernel_range: /* 31 insns */
        /* %o0=start, %o1=end */
        cmp             %o0, %o1
        be,pn           %xcc, 2f
-        sethi          %hi(PAGE_SIZE), %g3
-       mov             %o0, %g1
-       sub             %o1, %g1, %g2
+        sub            %o1, %o0, %g2
+       srlx            %g2, 18, %g3
+       brnz,pn         %g3, 4f
+        mov            %o0, %g1
+       sethi           %hi(PAGE_SIZE), %g3
        sub             %g2, %g3, %g2
 1:     add             %g1, %g2, %o0   /* ARG0: virtual address */
        mov             0, %o1          /* ARG1: mmu context */
        mov             HV_MMU_ALL, %o2 /* ARG2: flags */
        ta              HV_MMU_UNMAP_ADDR_TRAP
-       brnz,pn         %o0, __hypervisor_tlb_tl0_error
+       brnz,pn         %o0, 3f
         mov            HV_MMU_UNMAP_ADDR_TRAP, %o1
        brnz,pt         %g2, 1b
         sub            %g2, %g3, %g2
 2:     retl
         nop
+3:     sethi           %hi(__hypervisor_tlb_tl0_error), %o2
+       jmpl            %o2 + %lo(__hypervisor_tlb_tl0_error), %g0
+        nop
+4:     mov             0, %o0          /* ARG0: CPU lists unimplemented */
+       mov             0, %o1          /* ARG1: CPU lists unimplemented */
+       mov             0, %o2          /* ARG2: mmu context == nucleus */
+       mov             HV_MMU_ALL, %o3 /* ARG3: flags */
+       mov             HV_FAST_MMU_DEMAP_CTX, %o5
+       ta              HV_FAST_TRAP
+       brnz,pn         %o0, 3b
+        mov            HV_FAST_MMU_DEMAP_CTX, %o1
+       retl
+        nop
 
 #ifdef DCACHE_ALIASING_POSSIBLE
        /* XXX Niagara and friends have an 8K cache, so no aliasing is
@@ -394,43 +511,6 @@ tlb_patch_one:
        retl
         nop
 
-       .globl          cheetah_patch_cachetlbops
-cheetah_patch_cachetlbops:
-       save            %sp, -128, %sp
-
-       sethi           %hi(__flush_tlb_mm), %o0
-       or              %o0, %lo(__flush_tlb_mm), %o0
-       sethi           %hi(__cheetah_flush_tlb_mm), %o1
-       or              %o1, %lo(__cheetah_flush_tlb_mm), %o1
-       call            tlb_patch_one
-        mov            19, %o2
-
-       sethi           %hi(__flush_tlb_page), %o0
-       or              %o0, %lo(__flush_tlb_page), %o0
-       sethi           %hi(__cheetah_flush_tlb_page), %o1
-       or              %o1, %lo(__cheetah_flush_tlb_page), %o1
-       call            tlb_patch_one
-        mov            22, %o2
-
-       sethi           %hi(__flush_tlb_pending), %o0
-       or              %o0, %lo(__flush_tlb_pending), %o0
-       sethi           %hi(__cheetah_flush_tlb_pending), %o1
-       or              %o1, %lo(__cheetah_flush_tlb_pending), %o1
-       call            tlb_patch_one
-        mov            27, %o2
-
-#ifdef DCACHE_ALIASING_POSSIBLE
-       sethi           %hi(__flush_dcache_page), %o0
-       or              %o0, %lo(__flush_dcache_page), %o0
-       sethi           %hi(__cheetah_flush_dcache_page), %o1
-       or              %o1, %lo(__cheetah_flush_dcache_page), %o1
-       call            tlb_patch_one
-        mov            11, %o2
-#endif /* DCACHE_ALIASING_POSSIBLE */
-
-       ret
-        restore
-
 #ifdef CONFIG_SMP
        /* These are all called by the slaves of a cross call, at
         * trap level 1, with interrupts fully disabled.
@@ -447,7 +527,7 @@ cheetah_patch_cachetlbops:
         */
        .align          32
        .globl          xcall_flush_tlb_mm
-xcall_flush_tlb_mm:    /* 21 insns */
+xcall_flush_tlb_mm:    /* 24 insns */
        mov             PRIMARY_CONTEXT, %g2
        ldxa            [%g2] ASI_DMMU, %g3
        srlx            %g3, CTX_PGSZ1_NUC_SHIFT, %g4
@@ -469,9 +549,12 @@ xcall_flush_tlb_mm:        /* 21 insns */
        nop
        nop
        nop
+       nop
+       nop
+       nop
 
        .globl          xcall_flush_tlb_page
-xcall_flush_tlb_page:  /* 17 insns */
+xcall_flush_tlb_page:  /* 20 insns */
        /* %g5=context, %g1=vaddr */
        mov             PRIMARY_CONTEXT, %g4
        ldxa            [%g4] ASI_DMMU, %g2
@@ -490,15 +573,20 @@ xcall_flush_tlb_page:     /* 17 insns */
        retry
        nop
        nop
+       nop
+       nop
+       nop
 
        .globl          xcall_flush_tlb_kernel_range
-xcall_flush_tlb_kernel_range:  /* 25 insns */
+xcall_flush_tlb_kernel_range:  /* 44 insns */
        sethi           %hi(PAGE_SIZE - 1), %g2
        or              %g2, %lo(PAGE_SIZE - 1), %g2
        andn            %g1, %g2, %g1
        andn            %g7, %g2, %g7
        sub             %g7, %g1, %g3
-       add             %g2, 1, %g2
+       srlx            %g3, 18, %g2
+       brnz,pn         %g2, 2f
+        add            %g2, 1, %g2
        sub             %g3, %g2, %g3
        or              %g1, 0x20, %g1          ! Nucleus
 1:     stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
@@ -507,8 +595,25 @@ xcall_flush_tlb_kernel_range:      /* 25 insns */
        brnz,pt         %g3, 1b
         sub            %g3, %g2, %g3
        retry
-       nop
-       nop
+2:     mov             63 * 8, %g1
+1:     ldxa            [%g1] ASI_ITLB_DATA_ACCESS, %g2
+       andcc           %g2, 0x40, %g0                  /* _PAGE_L_4U */
+       bne,pn          %xcc, 2f
+        mov            TLB_TAG_ACCESS, %g2
+       stxa            %g0, [%g2] ASI_IMMU
+       stxa            %g0, [%g1] ASI_ITLB_DATA_ACCESS
+       membar          #Sync
+2:     ldxa            [%g1] ASI_DTLB_DATA_ACCESS, %g2
+       andcc           %g2, 0x40, %g0
+       bne,pn          %xcc, 2f
+        mov            TLB_TAG_ACCESS, %g2
+       stxa            %g0, [%g2] ASI_DMMU
+       stxa            %g0, [%g1] ASI_DTLB_DATA_ACCESS
+       membar          #Sync
+2:     sub             %g1, 8, %g1
+       brgez,pt        %g1, 1b
+        nop
+       retry
        nop
        nop
        nop
@@ -637,6 +742,52 @@ xcall_fetch_glob_pmu_n4:
 
        retry
 
+__cheetah_xcall_flush_tlb_kernel_range:        /* 44 insns */
+       sethi           %hi(PAGE_SIZE - 1), %g2
+       or              %g2, %lo(PAGE_SIZE - 1), %g2
+       andn            %g1, %g2, %g1
+       andn            %g7, %g2, %g7
+       sub             %g7, %g1, %g3
+       srlx            %g3, 18, %g2
+       brnz,pn         %g2, 2f
+        add            %g2, 1, %g2
+       sub             %g3, %g2, %g3
+       or              %g1, 0x20, %g1          ! Nucleus
+1:     stxa            %g0, [%g1 + %g3] ASI_DMMU_DEMAP
+       stxa            %g0, [%g1 + %g3] ASI_IMMU_DEMAP
+       membar          #Sync
+       brnz,pt         %g3, 1b
+        sub            %g3, %g2, %g3
+       retry
+2:     mov             0x80, %g2
+       stxa            %g0, [%g2] ASI_DMMU_DEMAP
+       membar          #Sync
+       stxa            %g0, [%g2] ASI_IMMU_DEMAP
+       membar          #Sync
+       retry
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+
 #ifdef DCACHE_ALIASING_POSSIBLE
        .align          32
        .globl          xcall_flush_dcache_page_cheetah
@@ -700,7 +851,7 @@ __hypervisor_tlb_xcall_error:
        ba,a,pt %xcc, rtrap
 
        .globl          __hypervisor_xcall_flush_tlb_mm
-__hypervisor_xcall_flush_tlb_mm: /* 21 insns */
+__hypervisor_xcall_flush_tlb_mm: /* 24 insns */
        /* %g5=ctx, g1,g2,g3,g4,g7=scratch, %g6=unusable */
        mov             %o0, %g2
        mov             %o1, %g3
@@ -714,7 +865,7 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
        mov             HV_FAST_MMU_DEMAP_CTX, %o5
        ta              HV_FAST_TRAP
        mov             HV_FAST_MMU_DEMAP_CTX, %g6
-       brnz,pn         %o0, __hypervisor_tlb_xcall_error
+       brnz,pn         %o0, 1f
         mov            %o0, %g5
        mov             %g2, %o0
        mov             %g3, %o1
@@ -723,9 +874,12 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */
        mov             %g7, %o5
        membar          #Sync
        retry
+1:     sethi           %hi(__hypervisor_tlb_xcall_error), %g4
+       jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+        nop
 
        .globl          __hypervisor_xcall_flush_tlb_page
-__hypervisor_xcall_flush_tlb_page: /* 17 insns */
+__hypervisor_xcall_flush_tlb_page: /* 20 insns */
        /* %g5=ctx, %g1=vaddr */
        mov             %o0, %g2
        mov             %o1, %g3
@@ -737,42 +891,64 @@ __hypervisor_xcall_flush_tlb_page: /* 17 insns */
        sllx            %o0, PAGE_SHIFT, %o0
        ta              HV_MMU_UNMAP_ADDR_TRAP
        mov             HV_MMU_UNMAP_ADDR_TRAP, %g6
-       brnz,a,pn       %o0, __hypervisor_tlb_xcall_error
+       brnz,a,pn       %o0, 1f
         mov            %o0, %g5
        mov             %g2, %o0
        mov             %g3, %o1
        mov             %g4, %o2
        membar          #Sync
        retry
+1:     sethi           %hi(__hypervisor_tlb_xcall_error), %g4
+       jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+        nop
 
        .globl          __hypervisor_xcall_flush_tlb_kernel_range
-__hypervisor_xcall_flush_tlb_kernel_range: /* 25 insns */
+__hypervisor_xcall_flush_tlb_kernel_range: /* 44 insns */
        /* %g1=start, %g7=end, g2,g3,g4,g5,g6=scratch */
        sethi           %hi(PAGE_SIZE - 1), %g2
        or              %g2, %lo(PAGE_SIZE - 1), %g2
        andn            %g1, %g2, %g1
        andn            %g7, %g2, %g7
        sub             %g7, %g1, %g3
+       srlx            %g3, 18, %g7
        add             %g2, 1, %g2
        sub             %g3, %g2, %g3
        mov             %o0, %g2
        mov             %o1, %g4
-       mov             %o2, %g7
+       brnz,pn         %g7, 2f
+        mov            %o2, %g7
 1:     add             %g1, %g3, %o0   /* ARG0: virtual address */
        mov             0, %o1          /* ARG1: mmu context */
        mov             HV_MMU_ALL, %o2 /* ARG2: flags */
        ta              HV_MMU_UNMAP_ADDR_TRAP
        mov             HV_MMU_UNMAP_ADDR_TRAP, %g6
-       brnz,pn         %o0, __hypervisor_tlb_xcall_error
+       brnz,pn         %o0, 1f
         mov            %o0, %g5
        sethi           %hi(PAGE_SIZE), %o2
        brnz,pt         %g3, 1b
         sub            %g3, %o2, %g3
-       mov             %g2, %o0
+5:     mov             %g2, %o0
        mov             %g4, %o1
        mov             %g7, %o2
        membar          #Sync
        retry
+1:     sethi           %hi(__hypervisor_tlb_xcall_error), %g4
+       jmpl            %g4 + %lo(__hypervisor_tlb_xcall_error), %g0
+        nop
+2:     mov             %o3, %g1
+       mov             %o5, %g3
+       mov             0, %o0          /* ARG0: CPU lists unimplemented */
+       mov             0, %o1          /* ARG1: CPU lists unimplemented */
+       mov             0, %o2          /* ARG2: mmu context == nucleus */
+       mov             HV_MMU_ALL, %o3 /* ARG3: flags */
+       mov             HV_FAST_MMU_DEMAP_CTX, %o5
+       ta              HV_FAST_TRAP
+       mov             %g1, %o3
+       brz,pt          %o0, 5b
+        mov            %g3, %o5
+       mov             HV_FAST_MMU_DEMAP_CTX, %g6
+       ba,pt           %xcc, 1b
+        clr            %g5
 
        /* These just get rescheduled to PIL vectors. */
        .globl          xcall_call_function
@@ -809,6 +985,58 @@ xcall_kgdb_capture:
 
 #endif /* CONFIG_SMP */
 
+       .globl          cheetah_patch_cachetlbops
+cheetah_patch_cachetlbops:
+       save            %sp, -128, %sp
+
+       sethi           %hi(__flush_tlb_mm), %o0
+       or              %o0, %lo(__flush_tlb_mm), %o0
+       sethi           %hi(__cheetah_flush_tlb_mm), %o1
+       or              %o1, %lo(__cheetah_flush_tlb_mm), %o1
+       call            tlb_patch_one
+        mov            19, %o2
+
+       sethi           %hi(__flush_tlb_page), %o0
+       or              %o0, %lo(__flush_tlb_page), %o0
+       sethi           %hi(__cheetah_flush_tlb_page), %o1
+       or              %o1, %lo(__cheetah_flush_tlb_page), %o1
+       call            tlb_patch_one
+        mov            22, %o2
+
+       sethi           %hi(__flush_tlb_pending), %o0
+       or              %o0, %lo(__flush_tlb_pending), %o0
+       sethi           %hi(__cheetah_flush_tlb_pending), %o1
+       or              %o1, %lo(__cheetah_flush_tlb_pending), %o1
+       call            tlb_patch_one
+        mov            27, %o2
+
+       sethi           %hi(__flush_tlb_kernel_range), %o0
+       or              %o0, %lo(__flush_tlb_kernel_range), %o0
+       sethi           %hi(__cheetah_flush_tlb_kernel_range), %o1
+       or              %o1, %lo(__cheetah_flush_tlb_kernel_range), %o1
+       call            tlb_patch_one
+        mov            31, %o2
+
+#ifdef DCACHE_ALIASING_POSSIBLE
+       sethi           %hi(__flush_dcache_page), %o0
+       or              %o0, %lo(__flush_dcache_page), %o0
+       sethi           %hi(__cheetah_flush_dcache_page), %o1
+       or              %o1, %lo(__cheetah_flush_dcache_page), %o1
+       call            tlb_patch_one
+        mov            11, %o2
+#endif /* DCACHE_ALIASING_POSSIBLE */
+
+#ifdef CONFIG_SMP
+       sethi           %hi(xcall_flush_tlb_kernel_range), %o0
+       or              %o0, %lo(xcall_flush_tlb_kernel_range), %o0
+       sethi           %hi(__cheetah_xcall_flush_tlb_kernel_range), %o1
+       or              %o1, %lo(__cheetah_xcall_flush_tlb_kernel_range), %o1
+       call            tlb_patch_one
+        mov            44, %o2
+#endif /* CONFIG_SMP */
+
+       ret
+        restore
 
        .globl          hypervisor_patch_cachetlbops
 hypervisor_patch_cachetlbops:
@@ -819,28 +1047,28 @@ hypervisor_patch_cachetlbops:
        sethi           %hi(__hypervisor_flush_tlb_mm), %o1
        or              %o1, %lo(__hypervisor_flush_tlb_mm), %o1
        call            tlb_patch_one
-        mov            10, %o2
+        mov            19, %o2
 
        sethi           %hi(__flush_tlb_page), %o0
        or              %o0, %lo(__flush_tlb_page), %o0
        sethi           %hi(__hypervisor_flush_tlb_page), %o1
        or              %o1, %lo(__hypervisor_flush_tlb_page), %o1
        call            tlb_patch_one
-        mov            11, %o2
+        mov            22, %o2
 
        sethi           %hi(__flush_tlb_pending), %o0
        or              %o0, %lo(__flush_tlb_pending), %o0
        sethi           %hi(__hypervisor_flush_tlb_pending), %o1
        or              %o1, %lo(__hypervisor_flush_tlb_pending), %o1
        call            tlb_patch_one
-        mov            16, %o2
+        mov            27, %o2
 
        sethi           %hi(__flush_tlb_kernel_range), %o0
        or              %o0, %lo(__flush_tlb_kernel_range), %o0
        sethi           %hi(__hypervisor_flush_tlb_kernel_range), %o1
        or              %o1, %lo(__hypervisor_flush_tlb_kernel_range), %o1
        call            tlb_patch_one
-        mov            16, %o2
+        mov            31, %o2
 
 #ifdef DCACHE_ALIASING_POSSIBLE
        sethi           %hi(__flush_dcache_page), %o0
@@ -857,21 +1085,21 @@ hypervisor_patch_cachetlbops:
        sethi           %hi(__hypervisor_xcall_flush_tlb_mm), %o1
        or              %o1, %lo(__hypervisor_xcall_flush_tlb_mm), %o1
        call            tlb_patch_one
-        mov            21, %o2
+        mov            24, %o2
 
        sethi           %hi(xcall_flush_tlb_page), %o0
        or              %o0, %lo(xcall_flush_tlb_page), %o0
        sethi           %hi(__hypervisor_xcall_flush_tlb_page), %o1
        or              %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
        call            tlb_patch_one
-        mov            17, %o2
+        mov            20, %o2
 
        sethi           %hi(xcall_flush_tlb_kernel_range), %o0
        or              %o0, %lo(xcall_flush_tlb_kernel_range), %o0
        sethi           %hi(__hypervisor_xcall_flush_tlb_kernel_range), %o1
        or              %o1, %lo(__hypervisor_xcall_flush_tlb_kernel_range), %o1
        call            tlb_patch_one
-        mov            25, %o2
+        mov            44, %o2
 #endif /* CONFIG_SMP */
 
        ret
index 77f28ce..9976fce 100644 (file)
@@ -5,8 +5,8 @@
 OBJECT_FILES_NON_STANDARD_entry_$(BITS).o   := y
 OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y
 
-CFLAGS_syscall_64.o            += -Wno-override-init
-CFLAGS_syscall_32.o            += -Wno-override-init
+CFLAGS_syscall_64.o            += $(call cc-option,-Wno-override-init,)
+CFLAGS_syscall_32.o            += $(call cc-option,-Wno-override-init,)
 obj-y                          := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
 obj-y                          += common.o
 
index ff6ef7b..2b36185 100644 (file)
 380    i386    pkey_mprotect           sys_pkey_mprotect
 381    i386    pkey_alloc              sys_pkey_alloc
 382    i386    pkey_free               sys_pkey_free
-#383   i386    pkey_get                sys_pkey_get
-#384   i386    pkey_set                sys_pkey_set
index 2f024d0..e93ef0b 100644 (file)
 329    common  pkey_mprotect           sys_pkey_mprotect
 330    common  pkey_alloc              sys_pkey_alloc
 331    common  pkey_free               sys_pkey_free
-#332   common  pkey_get                sys_pkey_get
-#333   common  pkey_set                sys_pkey_set
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index a3a9eb8..a74a2db 100644 (file)
@@ -3607,10 +3607,14 @@ __init int intel_pmu_init(void)
 
        /*
         * Quirk: v2 perfmon does not report fixed-purpose events, so
-        * assume at least 3 events:
+        * assume at least 3 events, when not running in a hypervisor:
         */
-       if (version > 1)
-               x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
+       if (version > 1) {
+               int assume = 3 * !boot_cpu_has(X86_FEATURE_HYPERVISOR);
+
+               x86_pmu.num_counters_fixed =
+                       max((int)edx.split.num_counters_fixed, assume);
+       }
 
        if (boot_cpu_has(X86_FEATURE_PDCM)) {
                u64 capabilities;
@@ -3898,6 +3902,7 @@ __init int intel_pmu_init(void)
                break;
 
        case INTEL_FAM6_XEON_PHI_KNL:
+       case INTEL_FAM6_XEON_PHI_KNM:
                memcpy(hw_cache_event_ids,
                       slm_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs,
@@ -3912,7 +3917,7 @@ __init int intel_pmu_init(void)
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
 
-               pr_cont("Knights Landing events, ");
+               pr_cont("Knights Landing/Mill events, ");
                break;
 
        case INTEL_FAM6_SKYLAKE_MOBILE:
index 3ca87b5..4f5ac72 100644 (file)
@@ -48,7 +48,8 @@
  *                            Scope: Core
  *     MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
  *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW
+ *                                             SKL,KNL
  *                            Scope: Core
  *     MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
  *                            perf code: 0x03
  *                            Scope: Core
  *     MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
  *                            perf code: 0x00
- *                            Available model: SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SNB,IVB,HSW,BDW,SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
  *                            perf code: 0x01
- *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
  *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW
+ *                                             SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
  *                            perf code: 0x03
@@ -118,6 +120,7 @@ struct cstate_model {
 
 /* Quirk flags */
 #define SLM_PKG_C6_USE_C7_MSR  (1UL << 0)
+#define KNL_CORE_C6_MSR                (1UL << 1)
 
 struct perf_cstate_msr {
        u64     msr;
@@ -488,6 +491,18 @@ static const struct cstate_model slm_cstates __initconst = {
        .quirks                 = SLM_PKG_C6_USE_C7_MSR,
 };
 
+
+static const struct cstate_model knl_cstates __initconst = {
+       .core_events            = BIT(PERF_CSTATE_CORE_C6_RES),
+
+       .pkg_events             = BIT(PERF_CSTATE_PKG_C2_RES) |
+                                 BIT(PERF_CSTATE_PKG_C3_RES) |
+                                 BIT(PERF_CSTATE_PKG_C6_RES),
+       .quirks                 = KNL_CORE_C6_MSR,
+};
+
+
+
 #define X86_CSTATES_MODEL(model, states)                               \
        { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) }
 
@@ -523,6 +538,8 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
 
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE,  snb_cstates),
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
+
+       X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
        { },
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
@@ -558,6 +575,11 @@ static int __init cstate_probe(const struct cstate_model *cm)
        if (cm->quirks & SLM_PKG_C6_USE_C7_MSR)
                pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
 
+       /* KNL has different MSR for CORE C6 */
+       if (cm->quirks & KNL_CORE_C6_MSR)
+               pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY;
+
+
        has_cstate_core = cstate_probe_msr(cm->core_events,
                                           PERF_CSTATE_CORE_EVENT_MAX,
                                           core_msr, core_events_attrs);
index fc6cf21..81b321a 100644 (file)
@@ -458,8 +458,8 @@ void intel_pmu_lbr_del(struct perf_event *event)
        if (!x86_pmu.lbr_nr)
                return;
 
-       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
-                                       event->ctx->task_ctx_data) {
+       if (branch_user_callstack(cpuc->br_sel) &&
+           event->ctx->task_ctx_data) {
                task_ctx = event->ctx->task_ctx_data;
                task_ctx->lbr_callstack_users--;
        }
index b0f0e83..0a535ce 100644 (file)
@@ -763,6 +763,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM, knl_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE,  skl_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init),
index d9844cc..efca268 100644 (file)
@@ -1349,6 +1349,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,    bdx_uncore_init),
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, bdx_uncore_init),
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL,   knl_uncore_init),
+       X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM,   knl_uncore_init),
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init),
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init),
        X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X,      skx_uncore_init),
index 1188bc8..a396292 100644 (file)
 #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 
 #define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
+#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
+#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
index 9ae5ab8..34a46dc 100644 (file)
@@ -64,5 +64,6 @@
 /* Xeon Phi */
 
 #define INTEL_FAM6_XEON_PHI_KNL                0x57 /* Knights Landing */
+#define INTEL_FAM6_XEON_PHI_KNM                0x85 /* Knights Mill */
 
 #endif /* _ASM_X86_INTEL_FAMILY_H */
index de25aad..d34bd37 100644 (file)
@@ -351,4 +351,10 @@ extern void arch_phys_wc_del(int handle);
 #define arch_phys_wc_add arch_phys_wc_add
 #endif
 
+#ifdef CONFIG_X86_PAT
+extern int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size);
+extern void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size);
+#define arch_io_reserve_memtype_wc arch_io_reserve_memtype_wc
+#endif
+
 #endif /* _ASM_X86_IO_H */
index 56f4c66..78f3760 100644 (file)
@@ -88,7 +88,6 @@
 
 #define MSR_IA32_RTIT_CTL              0x00000570
 #define MSR_IA32_RTIT_STATUS           0x00000571
-#define MSR_IA32_RTIT_STATUS           0x00000571
 #define MSR_IA32_RTIT_ADDR0_A          0x00000580
 #define MSR_IA32_RTIT_ADDR0_B          0x00000581
 #define MSR_IA32_RTIT_ADDR1_A          0x00000582
index 3d33a71..a34e0d4 100644 (file)
@@ -103,8 +103,10 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
 ({                                                     \
        long tmp;                                       \
        struct rw_semaphore* ret;                       \
+       register void *__sp asm(_ASM_SP);               \
+                                                       \
        asm volatile("# beginning down_write\n\t"       \
-                    LOCK_PREFIX "  xadd      %1,(%3)\n\t"      \
+                    LOCK_PREFIX "  xadd      %1,(%4)\n\t"      \
                     /* adds 0xffff0001, returns the old value */ \
                     "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \
                     /* was the active mask 0 before? */\
@@ -112,7 +114,7 @@ static inline bool __down_read_trylock(struct rw_semaphore *sem)
                     "  call " slow_path "\n"           \
                     "1:\n"                             \
                     "# ending down_write"              \
-                    : "+m" (sem->count), "=d" (tmp), "=a" (ret)        \
+                    : "+m" (sem->count), "=d" (tmp), "=a" (ret), "+r" (__sp) \
                     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
                     : "memory", "cc");                 \
        ret;                                            \
index 2aaca53..ad6f5eb 100644 (file)
@@ -52,6 +52,15 @@ struct task_struct;
 #include <asm/cpufeature.h>
 #include <linux/atomic.h>
 
+struct thread_info {
+       unsigned long           flags;          /* low level flags */
+};
+
+#define INIT_THREAD_INFO(tsk)                  \
+{                                              \
+       .flags          = 0,                    \
+}
+
 #define init_stack             (init_thread_union.stack)
 
 #else /* !__ASSEMBLY__ */
index 8a5abaa..931ced8 100644 (file)
@@ -454,6 +454,7 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
                polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
 
        mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
+       acpi_penalize_sci_irq(bus_irq, trigger, polarity);
 
        /*
         * stash over-ride to indicate we've been here
index 620ab06..017bda1 100644 (file)
@@ -429,7 +429,7 @@ int __init save_microcode_in_initrd_amd(void)
         * We need the physical address of the container for both bitness since
         * boot_params.hdr.ramdisk_image is a physical address.
         */
-       cont    = __pa(container);
+       cont    = __pa_nodebug(container);
        cont_va = container;
 #endif
 
index 8cb57df..1db8dc4 100644 (file)
@@ -32,6 +32,8 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 
        static const struct cpuid_bit cpuid_bits[] = {
                { X86_FEATURE_INTEL_PT,         CR_EBX,25, 0x00000007, 0 },
+               { X86_FEATURE_AVX512_4VNNIW,    CR_EDX, 2, 0x00000007, 0 },
+               { X86_FEATURE_AVX512_4FMAPS,    CR_EDX, 3, 0x00000007, 0 },
                { X86_FEATURE_APERFMPERF,       CR_ECX, 0, 0x00000006, 0 },
                { X86_FEATURE_EPB,              CR_ECX, 3, 0x00000006, 0 },
                { X86_FEATURE_HW_PSTATE,        CR_EDX, 7, 0x80000007, 0 },
index 8116057..5130985 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/div64.h>
 #include <asm/x86_init.h>
 #include <asm/hypervisor.h>
+#include <asm/timer.h>
 #include <asm/apic.h>
 
 #define CPUID_VMWARE_INFO_LEAF 0x40000000
@@ -94,6 +95,10 @@ static void __init vmware_platform_setup(void)
        } else {
                pr_warn("Failed to get TSC freq from the hypervisor\n");
        }
+
+#ifdef CONFIG_X86_IO_APIC
+       no_timer_check = 1;
+#endif
 }
 
 /*
index b85fe5f..90e8dde 100644 (file)
@@ -350,7 +350,7 @@ int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
                 * continue building up new bios map based on this
                 * information
                 */
-               if (current_type != last_type) {
+               if (current_type != last_type || current_type == E820_PRAM) {
                        if (last_type != 0)      {
                                new_bios[new_bios_entry].size =
                                        change_point[chgidx]->addr - last_addr;
index 124aa5c..095ef7d 100644 (file)
@@ -74,6 +74,8 @@ void fpu__xstate_clear_all_cpu_caps(void)
        setup_clear_cpu_cap(X86_FEATURE_MPX);
        setup_clear_cpu_cap(X86_FEATURE_XGETBV1);
        setup_clear_cpu_cap(X86_FEATURE_PKU);
+       setup_clear_cpu_cap(X86_FEATURE_AVX512_4VNNIW);
+       setup_clear_cpu_cap(X86_FEATURE_AVX512_4FMAPS);
 }
 
 /*
index 28cee01..d9d8d16 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
 #include <linux/frame.h>
+#include <linux/kasan.h>
 
 #include <asm/text-patching.h>
 #include <asm/cacheflush.h>
@@ -1057,9 +1058,10 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
         * tailcall optimization. So, to be absolutely safe
         * we also save and restore enough stack bytes to cover
         * the argument area.
+        * Use __memcpy() to avoid KASAN stack out-of-bounds reports as we copy
+        * raw stack chunk with redzones:
         */
-       memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
-              MIN_STACK_SIZE(addr));
+       __memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr, MIN_STACK_SIZE(addr));
        regs->flags &= ~X86_EFLAGS_IF;
        trace_hardirqs_off();
        regs->ip = (unsigned long)(jp->entry);
@@ -1080,6 +1082,9 @@ void jprobe_return(void)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
+       /* Unpoison stack redzones in the frames we are going to jump over. */
+       kasan_unpoison_stack_above_sp_to(kcb->jprobe_saved_sp);
+
        asm volatile (
 #ifdef CONFIG_X86_64
                        "       xchg   %%rbx,%%rsp      \n"
@@ -1118,7 +1123,7 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
                /* It's OK to start function graph tracing again */
                unpause_graph_tracing();
                *regs = kcb->jprobe_saved_regs;
-               memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp));
+               __memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp));
                preempt_enable_no_resched();
                return 1;
        }
index efe73aa..7b0d3da 100644 (file)
 
 #ifdef CC_USING_FENTRY
 # define function_hook __fentry__
+EXPORT_SYMBOL(__fentry__)
 #else
 # define function_hook mcount
+EXPORT_SYMBOL(mcount)
 #endif
 
 /* All cases save the original rbp (8 bytes) */
@@ -295,7 +297,6 @@ trace:
        jmp fgraph_trace
 END(function_hook)
 #endif /* CONFIG_DYNAMIC_FTRACE */
-EXPORT_SYMBOL(function_hook)
 #endif /* CONFIG_FUNCTION_TRACER */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
index 51402a7..0bee04d 100644 (file)
@@ -625,8 +625,6 @@ static void amd_disable_seq_and_redirect_scrub(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3,
                        amd_disable_seq_and_redirect_scrub);
 
-#endif
-
 #if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
 #include <linux/jump_label.h>
 #include <asm/string_64.h>
@@ -657,3 +655,4 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, quirk_intel_brickland_xeon_
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, quirk_intel_brickland_xeon_ras_cap);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2083, quirk_intel_purley_xeon_ras_cap);
 #endif
+#endif
index bbfbca5..9c337b0 100644 (file)
@@ -1221,11 +1221,16 @@ void __init setup_arch(char **cmdline_p)
         */
        get_smp_config();
 
+       /*
+        * Systems w/o ACPI and mptables might not have it mapped the local
+        * APIC yet, but prefill_possible_map() might need to access it.
+        */
+       init_apic_mappings();
+
        prefill_possible_map();
 
        init_cpu_to_node();
 
-       init_apic_mappings();
        io_apic_init_mappings();
 
        kvm_guest_init();
index 40df337..ec1f756 100644 (file)
@@ -105,9 +105,6 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
        /* Don't let flags to be set from userspace */
        act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
 
-       if (user_64bit_mode(current_pt_regs()))
-               return;
-
        if (in_ia32_syscall())
                act->sa.sa_flags |= SA_IA32_ABI;
        if (in_x32_syscall())
index 68f8cc2..c00cb64 100644 (file)
@@ -261,8 +261,10 @@ static inline void __smp_reschedule_interrupt(void)
 
 __visible void smp_reschedule_interrupt(struct pt_regs *regs)
 {
+       irq_enter();
        ack_APIC_irq();
        __smp_reschedule_interrupt();
+       irq_exit();
        /*
         * KVM uses this interrupt to force a cpu out of guest mode
         */
index 951f093..42f5eb7 100644 (file)
@@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void)
 
        /* No boot processor was found in mptable or ACPI MADT */
        if (!num_processors) {
-               int apicid = boot_cpu_physical_apicid;
-               int cpu = hard_smp_processor_id();
+               if (boot_cpu_has(X86_FEATURE_APIC)) {
+                       int apicid = boot_cpu_physical_apicid;
+                       int cpu = hard_smp_processor_id();
 
-               pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
+                       pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
 
-               /* Make sure boot cpu is enumerated */
-               if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
-                   apic->apic_id_valid(apicid))
-                       generic_processor_info(apicid, boot_cpu_apic_version);
+                       /* Make sure boot cpu is enumerated */
+                       if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+                           apic->apic_id_valid(apicid))
+                               generic_processor_info(apicid, boot_cpu_apic_version);
+               }
 
                if (!num_processors)
                        num_processors = 1;
index c9a0738..a23ce84 100644 (file)
@@ -57,7 +57,8 @@ static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
        unsigned char opcode[15];
        unsigned long addr = convert_ip_to_linear(child, regs);
 
-       copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
+       copied = access_process_vm(child, addr, opcode, sizeof(opcode),
+                       FOLL_FORCE);
        for (i = 0; i < copied; i++) {
                switch (opcode[i]) {
                /* popf and iret */
index 9298993..2d721e5 100644 (file)
@@ -47,7 +47,14 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
        get_stack_info(first_frame, state->task, &state->stack_info,
                       &state->stack_mask);
 
-       if (!__kernel_text_address(*first_frame))
+       /*
+        * The caller can provide the address of the first frame directly
+        * (first_frame) or indirectly (regs->sp) to indicate which stack frame
+        * to start unwinding at.  Skip ahead until we reach it.
+        */
+       if (!unwind_done(state) &&
+           (!on_stack(&state->stack_info, first_frame, sizeof(long)) ||
+           !__kernel_text_address(*first_frame)))
                unwind_next_frame(state);
 }
 EXPORT_SYMBOL_GPL(__unwind_start);
index c7220ba..1a22de7 100644 (file)
@@ -594,7 +594,7 @@ static void kvm_ioapic_reset(struct kvm_ioapic *ioapic)
        ioapic->irr = 0;
        ioapic->irr_delivered = 0;
        ioapic->id = 0;
-       memset(ioapic->irq_eoi, 0x00, IOAPIC_NUM_PINS);
+       memset(ioapic->irq_eoi, 0x00, sizeof(ioapic->irq_eoi));
        rtc_irq_eoi_tracking_reset(ioapic);
 }
 
index 6c633de..e375235 100644 (file)
@@ -5733,13 +5733,13 @@ static int kvmclock_cpu_online(unsigned int cpu)
 
 static void kvm_timer_init(void)
 {
-       int cpu;
-
        max_tsc_khz = tsc_khz;
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
 #ifdef CONFIG_CPU_FREQ
                struct cpufreq_policy policy;
+               int cpu;
+
                memset(&policy, 0, sizeof(policy));
                cpu = get_cpu();
                cpufreq_get_policy(&policy, cpu);
index b8b6a60..0d4fb3e 100644 (file)
@@ -435,7 +435,7 @@ slow_irqon:
 
                ret = get_user_pages_unlocked(start,
                                              (end - start) >> PAGE_SHIFT,
-                                             write, 0, pages);
+                                             pages, write ? FOLL_WRITE : 0);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index ddd2661..887e571 100644 (file)
@@ -104,10 +104,10 @@ void __init kernel_randomize_memory(void)
         * consistent with the vaddr_start/vaddr_end variables.
         */
        BUILD_BUG_ON(vaddr_start >= vaddr_end);
-       BUILD_BUG_ON(config_enabled(CONFIG_X86_ESPFIX64) &&
+       BUILD_BUG_ON(IS_ENABLED(CONFIG_X86_ESPFIX64) &&
                     vaddr_end >= EFI_VA_START);
-       BUILD_BUG_ON((config_enabled(CONFIG_X86_ESPFIX64) ||
-                     config_enabled(CONFIG_EFI)) &&
+       BUILD_BUG_ON((IS_ENABLED(CONFIG_X86_ESPFIX64) ||
+                     IS_ENABLED(CONFIG_EFI)) &&
                     vaddr_end >= __START_KERNEL_map);
        BUILD_BUG_ON(vaddr_end > __START_KERNEL_map);
 
index 8047687..e4f8009 100644 (file)
@@ -544,10 +544,9 @@ static int mpx_resolve_fault(long __user *addr, int write)
 {
        long gup_ret;
        int nr_pages = 1;
-       int force = 0;
 
-       gup_ret = get_user_pages((unsigned long)addr, nr_pages, write,
-                       force, NULL, NULL);
+       gup_ret = get_user_pages((unsigned long)addr, nr_pages,
+                       write ? FOLL_WRITE : 0, NULL, NULL);
        /*
         * get_user_pages() returns number of pages gotten.
         * 0 means we failed to fault in and get anything,
index 170cc4f..83e701f 100644 (file)
@@ -730,6 +730,20 @@ void io_free_memtype(resource_size_t start, resource_size_t end)
        free_memtype(start, end);
 }
 
+int arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size)
+{
+       enum page_cache_mode type = _PAGE_CACHE_MODE_WC;
+
+       return io_reserve_memtype(start, start + size, &type);
+}
+EXPORT_SYMBOL(arch_io_reserve_memtype_wc);
+
+void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size)
+{
+       io_free_memtype(start, start + size);
+}
+EXPORT_SYMBOL(arch_io_free_memtype_wc);
+
 pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                unsigned long size, pgprot_t vma_prot)
 {
index b4d5e95..4a6a5a2 100644 (file)
@@ -40,7 +40,15 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
                 */
                return BIOS_STATUS_UNIMPLEMENTED;
 
-       ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5);
+       /*
+        * If EFI_OLD_MEMMAP is set, we need to fall back to using our old EFI
+        * callback method, which uses efi_call() directly, with the kernel page tables:
+        */
+       if (unlikely(test_bit(EFI_OLD_MEMMAP, &efi.flags)))
+               ret = efi_call((void *)__va(tab->function), (u64)which, a1, a2, a3, a4, a5);
+       else
+               ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(uv_bios_call);
index 5766ead..60a5a5a 100644 (file)
@@ -36,7 +36,8 @@ int is_syscall(unsigned long addr)
                 * slow, but that doesn't matter, since it will be called only
                 * in case of singlestepping, if copy_from_user failed.
                 */
-               n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+               n = access_process_vm(current, addr, &instr, sizeof(instr),
+                               FOLL_FORCE);
                if (n != sizeof(instr)) {
                        printk(KERN_ERR "is_syscall : failed to read "
                               "instruction from 0x%lx\n", addr);
index 0b5c184..e30202b 100644 (file)
@@ -212,7 +212,8 @@ int is_syscall(unsigned long addr)
                 * slow, but that doesn't matter, since it will be called only
                 * in case of singlestepping, if copy_from_user failed.
                 */
-               n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
+               n = access_process_vm(current, addr, &instr, sizeof(instr),
+                               FOLL_FORCE);
                if (n != sizeof(instr)) {
                        printk("is_syscall : failed to read instruction from "
                               "0x%lx\n", addr);
index c0fdd57..bdd8556 100644 (file)
@@ -1837,6 +1837,7 @@ static void __init init_hvm_pv_info(void)
 
        xen_domain_type = XEN_HVM_DOMAIN;
 }
+#endif
 
 static int xen_cpu_up_prepare(unsigned int cpu)
 {
@@ -1887,6 +1888,7 @@ static int xen_cpu_up_online(unsigned int cpu)
        return 0;
 }
 
+#ifdef CONFIG_XEN_PVHVM
 #ifdef CONFIG_KEXEC_CORE
 static void xen_hvm_shutdown(void)
 {
index 7be53cb..6ebcef2 100644 (file)
@@ -133,6 +133,26 @@ retry:
 }
 EXPORT_SYMBOL_GPL(badblocks_check);
 
+static void badblocks_update_acked(struct badblocks *bb)
+{
+       u64 *p = bb->page;
+       int i;
+       bool unacked = false;
+
+       if (!bb->unacked_exist)
+               return;
+
+       for (i = 0; i < bb->count ; i++) {
+               if (!BB_ACK(p[i])) {
+                       unacked = true;
+                       break;
+               }
+       }
+
+       if (!unacked)
+               bb->unacked_exist = 0;
+}
+
 /**
  * badblocks_set() - Add a range of bad blocks to the table.
  * @bb:                the badblocks structure that holds all badblock information
@@ -294,6 +314,8 @@ int badblocks_set(struct badblocks *bb, sector_t s, int sectors,
        bb->changed = 1;
        if (!acknowledged)
                bb->unacked_exist = 1;
+       else
+               badblocks_update_acked(bb);
        write_sequnlock_irqrestore(&bb->lock, flags);
 
        return rv;
@@ -354,7 +376,8 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
                 * current range.  Earlier ranges could also overlap,
                 * but only this one can overlap the end of the range.
                 */
-               if (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) {
+               if ((BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > target) &&
+                   (BB_OFFSET(p[lo]) < target)) {
                        /* Partial overlap, leave the tail of this range */
                        int ack = BB_ACK(p[lo]);
                        sector_t a = BB_OFFSET(p[lo]);
@@ -377,7 +400,8 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
                        lo--;
                }
                while (lo >= 0 &&
-                      BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) {
+                      (BB_OFFSET(p[lo]) + BB_LEN(p[lo]) > s) &&
+                      (BB_OFFSET(p[lo]) < target)) {
                        /* This range does overlap */
                        if (BB_OFFSET(p[lo]) < s) {
                                /* Keep the early parts of this range. */
@@ -399,6 +423,7 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors)
                }
        }
 
+       badblocks_update_acked(bb);
        bb->changed = 1;
 out:
        write_sequnlock_irq(&bb->lock);
index 6a14b68..3c882cb 100644 (file)
@@ -342,6 +342,34 @@ static void flush_data_end_io(struct request *rq, int error)
        struct request_queue *q = rq->q;
        struct blk_flush_queue *fq = blk_get_flush_queue(q, NULL);
 
+       /*
+        * Updating q->in_flight[] here for making this tag usable
+        * early. Because in blk_queue_start_tag(),
+        * q->in_flight[BLK_RW_ASYNC] is used to limit async I/O and
+        * reserve tags for sync I/O.
+        *
+        * More importantly this way can avoid the following I/O
+        * deadlock:
+        *
+        * - suppose there are 40 fua requests comming to flush queue
+        *   and queue depth is 31
+        * - 30 rqs are scheduled then blk_queue_start_tag() can't alloc
+        *   tag for async I/O any more
+        * - all the 30 rqs are completed before FLUSH_PENDING_TIMEOUT
+        *   and flush_data_end_io() is called
+        * - the other rqs still can't go ahead if not updating
+        *   q->in_flight[BLK_RW_ASYNC] here, meantime these rqs
+        *   are held in flush data queue and make no progress of
+        *   handling post flush rq
+        * - only after the post flush rq is handled, all these rqs
+        *   can be completed
+        */
+
+       elv_completed_request(q, rq);
+
+       /* for avoiding double accounting */
+       rq->cmd_flags &= ~REQ_STARTED;
+
        /*
         * After populating an empty queue, kick it to avoid stall.  Read
         * the comment in flush_end_io().
index ddc2eed..f3d27a6 100644 (file)
@@ -1217,9 +1217,9 @@ static struct request *blk_mq_map_request(struct request_queue *q,
        blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx);
        rq = __blk_mq_alloc_request(&alloc_data, op, op_flags);
 
-       hctx->queued++;
-       data->hctx = hctx;
-       data->ctx = ctx;
+       data->hctx = alloc_data.hctx;
+       data->ctx = alloc_data.ctx;
+       data->hctx->queued++;
        return rq;
 }
 
index f0afdfb..194d20b 100644 (file)
@@ -21,7 +21,7 @@ obj-y                         += video/
 obj-y                          += idle/
 
 # IPMI must come before ACPI in order to provide IPMI opregion support
-obj-$(CONFIG_IPMI_HANDLER)     += char/ipmi/
+obj-y                          += char/ipmi/
 
 obj-$(CONFIG_ACPI)             += acpi/
 obj-$(CONFIG_SFI)              += sfi/
index f1e6dcc..54d48b9 100644 (file)
@@ -46,6 +46,7 @@
 #include "acdispat.h"
 #include "acnamesp.h"
 #include "actables.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dsinit")
@@ -214,23 +215,17 @@ acpi_ds_initialize_objects(u32 table_index,
 
        /* Walk entire namespace from the supplied root */
 
-       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-       if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
-       }
-
        /*
         * We don't use acpi_walk_namespace since we do not want to acquire
         * the namespace reader lock.
         */
        status =
            acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
-                                  ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object,
-                                  NULL, &info, NULL);
+                                  0, acpi_ds_init_one_object, NULL, &info,
+                                  NULL);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
        }
-       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
        status = acpi_get_table_by_index(table_index, &table);
        if (ACPI_FAILURE(status)) {
index 32e9ddc..2b3210f 100644 (file)
@@ -99,14 +99,11 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
                          "Method auto-serialization parse [%4.4s] %p\n",
                          acpi_ut_get_node_name(node), node));
 
-       acpi_ex_enter_interpreter();
-
        /* Create/Init a root op for the method parse tree */
 
        op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start);
        if (!op) {
-               status = AE_NO_MEMORY;
-               goto unlock;
+               return_ACPI_STATUS(AE_NO_MEMORY);
        }
 
        acpi_ps_set_name(op, node->name.integer);
@@ -118,8 +115,7 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
            acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL);
        if (!walk_state) {
                acpi_ps_free_op(op);
-               status = AE_NO_MEMORY;
-               goto unlock;
+               return_ACPI_STATUS(AE_NO_MEMORY);
        }
 
        status = acpi_ds_init_aml_walk(walk_state, op, node,
@@ -138,8 +134,6 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node,
        status = acpi_ps_parse_aml(walk_state);
 
        acpi_ps_delete_parse_tree(op);
-unlock:
-       acpi_ex_exit_interpreter();
        return_ACPI_STATUS(status);
 }
 
@@ -730,26 +724,6 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
 
                acpi_ds_method_data_delete_all(walk_state);
 
-               /*
-                * If method is serialized, release the mutex and restore the
-                * current sync level for this thread
-                */
-               if (method_desc->method.mutex) {
-
-                       /* Acquisition Depth handles recursive calls */
-
-                       method_desc->method.mutex->mutex.acquisition_depth--;
-                       if (!method_desc->method.mutex->mutex.acquisition_depth) {
-                               walk_state->thread->current_sync_level =
-                                   method_desc->method.mutex->mutex.
-                                   original_sync_level;
-
-                               acpi_os_release_mutex(method_desc->method.
-                                                     mutex->mutex.os_mutex);
-                               method_desc->method.mutex->mutex.thread_id = 0;
-                       }
-               }
-
                /*
                 * Delete any namespace objects created anywhere within the
                 * namespace by the execution of this method. Unless:
@@ -786,6 +760,26 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                                    ~ACPI_METHOD_MODIFIED_NAMESPACE;
                        }
                }
+
+               /*
+                * If method is serialized, release the mutex and restore the
+                * current sync level for this thread
+                */
+               if (method_desc->method.mutex) {
+
+                       /* Acquisition Depth handles recursive calls */
+
+                       method_desc->method.mutex->mutex.acquisition_depth--;
+                       if (!method_desc->method.mutex->mutex.acquisition_depth) {
+                               walk_state->thread->current_sync_level =
+                                   method_desc->method.mutex->mutex.
+                                   original_sync_level;
+
+                               acpi_os_release_mutex(method_desc->method.
+                                                     mutex->mutex.os_mutex);
+                               method_desc->method.mutex->mutex.thread_id = 0;
+                       }
+               }
        }
 
        /* Decrement the thread count on the method */
index 028b22a..e362182 100644 (file)
@@ -607,11 +607,9 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                                }
                        }
 
-                       acpi_ex_exit_interpreter();
                        status =
                            acpi_ev_initialize_region
                            (acpi_ns_get_attached_object(node), FALSE);
-                       acpi_ex_enter_interpreter();
 
                        if (ACPI_FAILURE(status)) {
                                /*
index 3843f1f..75ddd16 100644 (file)
@@ -45,6 +45,7 @@
 #include "accommon.h"
 #include "acevents.h"
 #include "acnamesp.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_EVENTS
 ACPI_MODULE_NAME("evrgnini")
@@ -597,9 +598,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
                                        }
                                }
 
+                               acpi_ex_exit_interpreter();
                                status =
                                    acpi_ev_execute_reg_method(region_obj,
                                                               ACPI_REG_CONNECT);
+                               acpi_ex_enter_interpreter();
 
                                if (acpi_ns_locked) {
                                        status =
index 334d3c5..d1f2014 100644 (file)
@@ -137,7 +137,9 @@ unlock:
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "**** Begin Table Object Initialization\n"));
 
+       acpi_ex_enter_interpreter();
        status = acpi_ds_initialize_objects(table_index, node);
+       acpi_ex_exit_interpreter();
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "**** Completed Table Object Initialization\n"));
index f0a029e..0d099a2 100644 (file)
@@ -662,7 +662,7 @@ static int ghes_proc(struct ghes *ghes)
        ghes_do_proc(ghes, ghes->estatus);
 out:
        ghes_clear_estatus(ghes);
-       return 0;
+       return rc;
 }
 
 static void ghes_add_timer(struct ghes *ghes)
index c983bf7..bc3d914 100644 (file)
@@ -87,6 +87,7 @@ struct acpi_pci_link {
 
 static LIST_HEAD(acpi_link_list);
 static DEFINE_MUTEX(acpi_link_lock);
+static int sci_irq = -1, sci_penalty;
 
 /* --------------------------------------------------------------------------
                             PCI Link Device Management
@@ -496,25 +497,13 @@ static int acpi_irq_get_penalty(int irq)
 {
        int penalty = 0;
 
-       /*
-       * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
-       * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
-       * use for PCI IRQs.
-       */
-       if (irq == acpi_gbl_FADT.sci_interrupt) {
-               u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
-
-               if (type != IRQ_TYPE_LEVEL_LOW)
-                       penalty += PIRQ_PENALTY_ISA_ALWAYS;
-               else
-                       penalty += PIRQ_PENALTY_PCI_USING;
-       }
+       if (irq == sci_irq)
+               penalty += sci_penalty;
 
        if (irq < ACPI_MAX_ISA_IRQS)
                return penalty + acpi_isa_irq_penalty[irq];
 
-       penalty += acpi_irq_pci_sharing_penalty(irq);
-       return penalty;
+       return penalty + acpi_irq_pci_sharing_penalty(irq);
 }
 
 int __init acpi_irq_penalty_init(void)
@@ -619,6 +608,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
+               if (link->irq.active < ACPI_MAX_ISA_IRQS)
+                       acpi_isa_irq_penalty[link->irq.active] +=
+                               PIRQ_PENALTY_PCI_USING;
+
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
@@ -849,7 +842,7 @@ static int __init acpi_irq_penalty_update(char *str, int used)
                        continue;
 
                if (used)
-                       new_penalty = acpi_irq_get_penalty(irq) +
+                       new_penalty = acpi_isa_irq_penalty[irq] +
                                        PIRQ_PENALTY_ISA_USED;
                else
                        new_penalty = 0;
@@ -871,7 +864,7 @@ static int __init acpi_irq_penalty_update(char *str, int used)
 void acpi_penalize_isa_irq(int irq, int active)
 {
        if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
-               acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
+               acpi_isa_irq_penalty[irq] +=
                  (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
 }
 
@@ -881,6 +874,17 @@ bool acpi_isa_irq_available(int irq)
                    acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
+void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
+{
+       sci_irq = irq;
+
+       if (trigger == ACPI_MADT_TRIGGER_LEVEL &&
+           polarity == ACPI_MADT_POLARITY_ACTIVE_LOW)
+               sci_penalty = PIRQ_PENALTY_PCI_USING;
+       else
+               sci_penalty = PIRQ_PENALTY_ISA_ALWAYS;
+}
+
 /*
  * Over-ride default table to reserve additional IRQs for use by ISA
  * e.g. acpi_irq_isa=5
index 562af94..3c71b98 100644 (file)
@@ -1002,7 +1002,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
 
 
 static struct binder_ref *binder_get_ref(struct binder_proc *proc,
-                                        uint32_t desc)
+                                        u32 desc, bool need_strong_ref)
 {
        struct rb_node *n = proc->refs_by_desc.rb_node;
        struct binder_ref *ref;
@@ -1010,12 +1010,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
        while (n) {
                ref = rb_entry(n, struct binder_ref, rb_node_desc);
 
-               if (desc < ref->desc)
+               if (desc < ref->desc) {
                        n = n->rb_left;
-               else if (desc > ref->desc)
+               } else if (desc > ref->desc) {
                        n = n->rb_right;
-               else
+               } else if (need_strong_ref && !ref->strong) {
+                       binder_user_error("tried to use weak ref as strong ref\n");
+                       return NULL;
+               } else {
                        return ref;
+               }
        }
        return NULL;
 }
@@ -1285,7 +1289,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                } break;
                case BINDER_TYPE_HANDLE:
                case BINDER_TYPE_WEAK_HANDLE: {
-                       struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+                       struct binder_ref *ref;
+
+                       ref = binder_get_ref(proc, fp->handle,
+                                            fp->type == BINDER_TYPE_HANDLE);
 
                        if (ref == NULL) {
                                pr_err("transaction release %d bad handle %d\n",
@@ -1380,7 +1387,7 @@ static void binder_transaction(struct binder_proc *proc,
                if (tr->target.handle) {
                        struct binder_ref *ref;
 
-                       ref = binder_get_ref(proc, tr->target.handle);
+                       ref = binder_get_ref(proc, tr->target.handle, true);
                        if (ref == NULL) {
                                binder_user_error("%d:%d got transaction to invalid handle\n",
                                        proc->pid, thread->pid);
@@ -1577,7 +1584,9 @@ static void binder_transaction(struct binder_proc *proc,
                                fp->type = BINDER_TYPE_HANDLE;
                        else
                                fp->type = BINDER_TYPE_WEAK_HANDLE;
+                       fp->binder = 0;
                        fp->handle = ref->desc;
+                       fp->cookie = 0;
                        binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
                                       &thread->todo);
 
@@ -1589,7 +1598,10 @@ static void binder_transaction(struct binder_proc *proc,
                } break;
                case BINDER_TYPE_HANDLE:
                case BINDER_TYPE_WEAK_HANDLE: {
-                       struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+                       struct binder_ref *ref;
+
+                       ref = binder_get_ref(proc, fp->handle,
+                                            fp->type == BINDER_TYPE_HANDLE);
 
                        if (ref == NULL) {
                                binder_user_error("%d:%d got transaction with invalid handle, %d\n",
@@ -1624,7 +1636,9 @@ static void binder_transaction(struct binder_proc *proc,
                                        return_error = BR_FAILED_REPLY;
                                        goto err_binder_get_ref_for_node_failed;
                                }
+                               fp->binder = 0;
                                fp->handle = new_ref->desc;
+                               fp->cookie = 0;
                                binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
                                trace_binder_transaction_ref_to_ref(t, ref,
                                                                    new_ref);
@@ -1678,6 +1692,7 @@ static void binder_transaction(struct binder_proc *proc,
                        binder_debug(BINDER_DEBUG_TRANSACTION,
                                     "        fd %d -> %d\n", fp->handle, target_fd);
                        /* TODO: fput? */
+                       fp->binder = 0;
                        fp->handle = target_fd;
                } break;
 
@@ -1800,7 +1815,9 @@ static int binder_thread_write(struct binder_proc *proc,
                                                ref->desc);
                                }
                        } else
-                               ref = binder_get_ref(proc, target);
+                               ref = binder_get_ref(proc, target,
+                                                    cmd == BC_ACQUIRE ||
+                                                    cmd == BC_RELEASE);
                        if (ref == NULL) {
                                binder_user_error("%d:%d refcount change on invalid ref %d\n",
                                        proc->pid, thread->pid, target);
@@ -1996,7 +2013,7 @@ static int binder_thread_write(struct binder_proc *proc,
                        if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
                        ptr += sizeof(binder_uintptr_t);
-                       ref = binder_get_ref(proc, target);
+                       ref = binder_get_ref(proc, target, false);
                        if (ref == NULL) {
                                binder_user_error("%d:%d %s invalid ref %d\n",
                                        proc->pid, thread->pid,
index ba5f11c..9669fc7 100644 (file)
@@ -1418,30 +1418,33 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
         * Message mode could be enforced. In this case assume that advantage
         * of multipe MSIs is negated and use single MSI mode instead.
         */
-       nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
-                       PCI_IRQ_MSIX | PCI_IRQ_MSI);
-       if (nvec > 0) {
-               if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
-                       hpriv->get_irq_vector = ahci_get_irq_vector;
-                       hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
-                       return nvec;
+       if (n_ports > 1) {
+               nvec = pci_alloc_irq_vectors(pdev, n_ports, INT_MAX,
+                               PCI_IRQ_MSIX | PCI_IRQ_MSI);
+               if (nvec > 0) {
+                       if (!(readl(hpriv->mmio + HOST_CTL) & HOST_MRSM)) {
+                               hpriv->get_irq_vector = ahci_get_irq_vector;
+                               hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
+                               return nvec;
+                       }
+
+                       /*
+                        * Fallback to single MSI mode if the controller
+                        * enforced MRSM mode.
+                        */
+                       printk(KERN_INFO
+                               "ahci: MRSM is on, fallback to single MSI\n");
+                       pci_free_irq_vectors(pdev);
                }
 
                /*
-                * Fallback to single MSI mode if the controller enforced MRSM
-                * mode.
+                * -ENOSPC indicated we don't have enough vectors.  Don't bother
+                * trying a single vectors for any other error:
                 */
-               printk(KERN_INFO "ahci: MRSM is on, fallback to single MSI\n");
-               pci_free_irq_vectors(pdev);
+               if (nvec < 0 && nvec != -ENOSPC)
+                       return nvec;
        }
 
-       /*
-        * -ENOSPC indicated we don't have enough vectors.  Don't bother trying
-        * a single vectors for any other error:
-        */
-       if (nvec < 0 && nvec != -ENOSPC)
-               return nvec;
-
        /*
         * If the host is not capable of supporting per-port vectors, fall
         * back to single MSI before finally attempting single MSI-X.
@@ -1617,7 +1620,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                /* legacy intx interrupts */
                pci_intx(pdev, 1);
        }
-       hpriv->irq = pdev->irq;
+       hpriv->irq = pci_irq_vector(pdev, 0);
 
        if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
                host->flags |= ATA_HOST_PARALLEL_SCAN;
index fdf44ca..d02e7c0 100644 (file)
@@ -213,14 +213,16 @@ config DEBUG_DEVRES
          If you are unsure about this, Say N here.
 
 config DEBUG_TEST_DRIVER_REMOVE
-       bool "Test driver remove calls during probe"
+       bool "Test driver remove calls during probe (UNSTABLE)"
        depends on DEBUG_KERNEL
        help
          Say Y here if you want the Driver core to test driver remove functions
          by calling probe, remove, probe. This tests the remove path without
          having to unbind the driver or unload the driver module.
 
-         If you are unsure about this, say N here.
+         This option is expected to find errors and may render your system
+         unusable. You should say N here unless you are explicitly looking to
+         test this functionality.
 
 config SYS_HYPERVISOR
        bool
index 811e11c..0809cda 100644 (file)
@@ -2954,7 +2954,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
        case DAC960_PD_Controller:
          if (!request_region(Controller->IO_Address, 0x80,
                              Controller->FullModelName)) {
-               DAC960_Error("IO port 0x%d busy for Controller at\n",
+               DAC960_Error("IO port 0x%lx busy for Controller at\n",
                             Controller, Controller->IO_Address);
                goto Failure;
          }
@@ -2990,7 +2990,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
        case DAC960_P_Controller:
          if (!request_region(Controller->IO_Address, 0x80,
                              Controller->FullModelName)){
-               DAC960_Error("IO port 0x%d busy for Controller at\n",
+               DAC960_Error("IO port 0x%lx busy for Controller at\n",
                             Controller, Controller->IO_Address);
                goto Failure;
          }
index ba405b5..19a16b2 100644 (file)
@@ -164,7 +164,7 @@ static void sock_shutdown(struct nbd_device *nbd)
        spin_lock(&nbd->sock_lock);
 
        if (!nbd->sock) {
-               spin_unlock_irq(&nbd->sock_lock);
+               spin_unlock(&nbd->sock_lock);
                return;
        }
 
index abb7162..7b274ff 100644 (file)
@@ -415,15 +415,15 @@ struct rbd_device {
 };
 
 /*
- * Flag bits for rbd_dev->flags.  If atomicity is required,
- * rbd_dev->lock is used to protect access.
- *
- * Currently, only the "removing" flag (which is coupled with the
- * "open_count" field) requires atomic access.
+ * Flag bits for rbd_dev->flags:
+ * - REMOVING (which is coupled with rbd_dev->open_count) is protected
+ *   by rbd_dev->lock
+ * - BLACKLISTED is protected by rbd_dev->lock_rwsem
  */
 enum rbd_dev_flags {
        RBD_DEV_FLAG_EXISTS,    /* mapped snapshot has not been deleted */
        RBD_DEV_FLAG_REMOVING,  /* this mapping is being removed */
+       RBD_DEV_FLAG_BLACKLISTED, /* our ceph_client is blacklisted */
 };
 
 static DEFINE_MUTEX(client_mutex);     /* Serialize client creation */
@@ -3926,6 +3926,7 @@ static void rbd_reregister_watch(struct work_struct *work)
        struct rbd_device *rbd_dev = container_of(to_delayed_work(work),
                                            struct rbd_device, watch_dwork);
        bool was_lock_owner = false;
+       bool need_to_wake = false;
        int ret;
 
        dout("%s rbd_dev %p\n", __func__, rbd_dev);
@@ -3935,19 +3936,27 @@ static void rbd_reregister_watch(struct work_struct *work)
                was_lock_owner = rbd_release_lock(rbd_dev);
 
        mutex_lock(&rbd_dev->watch_mutex);
-       if (rbd_dev->watch_state != RBD_WATCH_STATE_ERROR)
-               goto fail_unlock;
+       if (rbd_dev->watch_state != RBD_WATCH_STATE_ERROR) {
+               mutex_unlock(&rbd_dev->watch_mutex);
+               goto out;
+       }
 
        ret = __rbd_register_watch(rbd_dev);
        if (ret) {
                rbd_warn(rbd_dev, "failed to reregister watch: %d", ret);
-               if (ret != -EBLACKLISTED)
+               if (ret == -EBLACKLISTED || ret == -ENOENT) {
+                       set_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags);
+                       need_to_wake = true;
+               } else {
                        queue_delayed_work(rbd_dev->task_wq,
                                           &rbd_dev->watch_dwork,
                                           RBD_RETRY_DELAY);
-               goto fail_unlock;
+               }
+               mutex_unlock(&rbd_dev->watch_mutex);
+               goto out;
        }
 
+       need_to_wake = true;
        rbd_dev->watch_state = RBD_WATCH_STATE_REGISTERED;
        rbd_dev->watch_cookie = rbd_dev->watch_handle->linger_id;
        mutex_unlock(&rbd_dev->watch_mutex);
@@ -3963,13 +3972,10 @@ static void rbd_reregister_watch(struct work_struct *work)
                                 ret);
        }
 
+out:
        up_write(&rbd_dev->lock_rwsem);
-       wake_requests(rbd_dev, true);
-       return;
-
-fail_unlock:
-       mutex_unlock(&rbd_dev->watch_mutex);
-       up_write(&rbd_dev->lock_rwsem);
+       if (need_to_wake)
+               wake_requests(rbd_dev, true);
 }
 
 /*
@@ -4074,7 +4080,9 @@ static void rbd_wait_state_locked(struct rbd_device *rbd_dev)
                up_read(&rbd_dev->lock_rwsem);
                schedule();
                down_read(&rbd_dev->lock_rwsem);
-       } while (rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED);
+       } while (rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED &&
+                !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags));
+
        finish_wait(&rbd_dev->lock_waitq, &wait);
 }
 
@@ -4166,8 +4174,16 @@ static void rbd_queue_workfn(struct work_struct *work)
 
        if (must_be_locked) {
                down_read(&rbd_dev->lock_rwsem);
-               if (rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED)
+               if (rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED &&
+                   !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags))
                        rbd_wait_state_locked(rbd_dev);
+
+               WARN_ON((rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED) ^
+                       !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags));
+               if (test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags)) {
+                       result = -EBLACKLISTED;
+                       goto err_unlock;
+               }
        }
 
        img_request = rbd_img_request_create(rbd_dev, offset, length, op_type,
index ef51c9c..b6bb58c 100644 (file)
@@ -310,7 +310,7 @@ static int bt_ti_probe(struct platform_device *pdev)
        BT_DBG("HCI device registered (hdev %p)", hdev);
 
        dev_set_drvdata(&pdev->dev, hst);
-       return err;
+       return 0;
 }
 
 static int bt_ti_remove(struct platform_device *pdev)
index 5ccb90e..8f6c23c 100644 (file)
@@ -643,6 +643,14 @@ static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
                },
                .driver_data = &acpi_active_low,
        },
+       {       /* Handle ThinkPad 8 tablets with BCM2E55 chipset ACPI ID */
+               .ident = "Lenovo ThinkPad 8",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"),
+               },
+               .driver_data = &acpi_active_low,
+       },
        { }
 };
 
index 7010dca..7875105 100644 (file)
@@ -111,6 +111,7 @@ config OMAP_OCP2SCP
 config QCOM_EBI2
        bool "Qualcomm External Bus Interface 2 (EBI2)"
        depends on HAS_IOMEM
+       depends on ARCH_QCOM || COMPILE_TEST
        help
          Say y here to enable support for the Qualcomm External Bus
          Interface 2, which can be used to connect things like NAND Flash,
index 4827945..d2d2c89 100644 (file)
@@ -84,14 +84,14 @@ static size_t rng_buffer_size(void)
 
 static void add_early_randomness(struct hwrng *rng)
 {
-       unsigned char bytes[16];
        int bytes_read;
+       size_t size = min_t(size_t, 16, rng_buffer_size());
 
        mutex_lock(&reading_mutex);
-       bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
+       bytes_read = rng_get_data(rng, rng_buffer, size, 1);
        mutex_unlock(&reading_mutex);
        if (bytes_read > 0)
-               add_device_randomness(bytes, bytes_read);
+               add_device_randomness(rng_buffer, bytes_read);
 }
 
 static inline void cleanup_rng(struct kref *kref)
index 5a9350b..7f81665 100644 (file)
@@ -76,3 +76,11 @@ config IPMI_POWEROFF
         the IPMI management controller is capable of this.
 
 endif # IPMI_HANDLER
+
+config ASPEED_BT_IPMI_BMC
+       depends on ARCH_ASPEED
+       tristate "BT IPMI bmc driver"
+       help
+         Provides a driver for the BT (Block Transfer) IPMI interface
+         found on Aspeed SOCs (AST2400 and AST2500). The driver
+         implements the BMC side of the BT interface.
index f3ffde1..0d98cd9 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o
 obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
 obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
+obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
new file mode 100644 (file)
index 0000000..b49e613
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2015-2016, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/atomic.h>
+#include <linux/bt-bmc.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+
+/*
+ * This is a BMC device used to communicate to the host
+ */
+#define DEVICE_NAME    "ipmi-bt-host"
+
+#define BT_IO_BASE     0xe4
+#define BT_IRQ         10
+
+#define BT_CR0         0x0
+#define   BT_CR0_IO_BASE               16
+#define   BT_CR0_IRQ                   12
+#define   BT_CR0_EN_CLR_SLV_RDP                0x8
+#define   BT_CR0_EN_CLR_SLV_WRP                0x4
+#define   BT_CR0_ENABLE_IBT            0x1
+#define BT_CR1         0x4
+#define   BT_CR1_IRQ_H2B       0x01
+#define   BT_CR1_IRQ_HBUSY     0x40
+#define BT_CR2         0x8
+#define   BT_CR2_IRQ_H2B       0x01
+#define   BT_CR2_IRQ_HBUSY     0x40
+#define BT_CR3         0xc
+#define BT_CTRL                0x10
+#define   BT_CTRL_B_BUSY               0x80
+#define   BT_CTRL_H_BUSY               0x40
+#define   BT_CTRL_OEM0                 0x20
+#define   BT_CTRL_SMS_ATN              0x10
+#define   BT_CTRL_B2H_ATN              0x08
+#define   BT_CTRL_H2B_ATN              0x04
+#define   BT_CTRL_CLR_RD_PTR           0x02
+#define   BT_CTRL_CLR_WR_PTR           0x01
+#define BT_BMC2HOST    0x14
+#define BT_INTMASK     0x18
+#define   BT_INTMASK_B2H_IRQEN         0x01
+#define   BT_INTMASK_B2H_IRQ           0x02
+#define   BT_INTMASK_BMC_HWRST         0x80
+
+#define BT_BMC_BUFFER_SIZE 256
+
+struct bt_bmc {
+       struct device           dev;
+       struct miscdevice       miscdev;
+       void __iomem            *base;
+       int                     irq;
+       wait_queue_head_t       queue;
+       struct timer_list       poll_timer;
+       struct mutex            mutex;
+};
+
+static atomic_t open_count = ATOMIC_INIT(0);
+
+static u8 bt_inb(struct bt_bmc *bt_bmc, int reg)
+{
+       return ioread8(bt_bmc->base + reg);
+}
+
+static void bt_outb(struct bt_bmc *bt_bmc, u8 data, int reg)
+{
+       iowrite8(data, bt_bmc->base + reg);
+}
+
+static void clr_rd_ptr(struct bt_bmc *bt_bmc)
+{
+       bt_outb(bt_bmc, BT_CTRL_CLR_RD_PTR, BT_CTRL);
+}
+
+static void clr_wr_ptr(struct bt_bmc *bt_bmc)
+{
+       bt_outb(bt_bmc, BT_CTRL_CLR_WR_PTR, BT_CTRL);
+}
+
+static void clr_h2b_atn(struct bt_bmc *bt_bmc)
+{
+       bt_outb(bt_bmc, BT_CTRL_H2B_ATN, BT_CTRL);
+}
+
+static void set_b_busy(struct bt_bmc *bt_bmc)
+{
+       if (!(bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_B_BUSY))
+               bt_outb(bt_bmc, BT_CTRL_B_BUSY, BT_CTRL);
+}
+
+static void clr_b_busy(struct bt_bmc *bt_bmc)
+{
+       if (bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_B_BUSY)
+               bt_outb(bt_bmc, BT_CTRL_B_BUSY, BT_CTRL);
+}
+
+static void set_b2h_atn(struct bt_bmc *bt_bmc)
+{
+       bt_outb(bt_bmc, BT_CTRL_B2H_ATN, BT_CTRL);
+}
+
+static u8 bt_read(struct bt_bmc *bt_bmc)
+{
+       return bt_inb(bt_bmc, BT_BMC2HOST);
+}
+
+static ssize_t bt_readn(struct bt_bmc *bt_bmc, u8 *buf, size_t n)
+{
+       int i;
+
+       for (i = 0; i < n; i++)
+               buf[i] = bt_read(bt_bmc);
+       return n;
+}
+
+static void bt_write(struct bt_bmc *bt_bmc, u8 c)
+{
+       bt_outb(bt_bmc, c, BT_BMC2HOST);
+}
+
+static ssize_t bt_writen(struct bt_bmc *bt_bmc, u8 *buf, size_t n)
+{
+       int i;
+
+       for (i = 0; i < n; i++)
+               bt_write(bt_bmc, buf[i]);
+       return n;
+}
+
+static void set_sms_atn(struct bt_bmc *bt_bmc)
+{
+       bt_outb(bt_bmc, BT_CTRL_SMS_ATN, BT_CTRL);
+}
+
+static struct bt_bmc *file_bt_bmc(struct file *file)
+{
+       return container_of(file->private_data, struct bt_bmc, miscdev);
+}
+
+static int bt_bmc_open(struct inode *inode, struct file *file)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+
+       if (atomic_inc_return(&open_count) == 1) {
+               clr_b_busy(bt_bmc);
+               return 0;
+       }
+
+       atomic_dec(&open_count);
+       return -EBUSY;
+}
+
+/*
+ * The BT (Block Transfer) interface means that entire messages are
+ * buffered by the host before a notification is sent to the BMC that
+ * there is data to be read. The first byte is the length and the
+ * message data follows. The read operation just tries to capture the
+ * whole before returning it to userspace.
+ *
+ * BT Message format :
+ *
+ *    Byte 1  Byte 2     Byte 3  Byte 4  Byte 5:N
+ *    Length  NetFn/LUN  Seq     Cmd     Data
+ *
+ */
+static ssize_t bt_bmc_read(struct file *file, char __user *buf,
+                          size_t count, loff_t *ppos)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+       u8 len;
+       int len_byte = 1;
+       u8 kbuffer[BT_BMC_BUFFER_SIZE];
+       ssize_t ret = 0;
+       ssize_t nread;
+
+       if (!access_ok(VERIFY_WRITE, buf, count))
+               return -EFAULT;
+
+       WARN_ON(*ppos);
+
+       if (wait_event_interruptible(bt_bmc->queue,
+                                    bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_H2B_ATN))
+               return -ERESTARTSYS;
+
+       mutex_lock(&bt_bmc->mutex);
+
+       if (unlikely(!(bt_inb(bt_bmc, BT_CTRL) & BT_CTRL_H2B_ATN))) {
+               ret = -EIO;
+               goto out_unlock;
+       }
+
+       set_b_busy(bt_bmc);
+       clr_h2b_atn(bt_bmc);
+       clr_rd_ptr(bt_bmc);
+
+       /*
+        * The BT frames start with the message length, which does not
+        * include the length byte.
+        */
+       kbuffer[0] = bt_read(bt_bmc);
+       len = kbuffer[0];
+
+       /* We pass the length back to userspace as well */
+       if (len + 1 > count)
+               len = count - 1;
+
+       while (len) {
+               nread = min_t(ssize_t, len, sizeof(kbuffer) - len_byte);
+
+               bt_readn(bt_bmc, kbuffer + len_byte, nread);
+
+               if (copy_to_user(buf, kbuffer, nread + len_byte)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               len -= nread;
+               buf += nread + len_byte;
+               ret += nread + len_byte;
+               len_byte = 0;
+       }
+
+       clr_b_busy(bt_bmc);
+
+out_unlock:
+       mutex_unlock(&bt_bmc->mutex);
+       return ret;
+}
+
+/*
+ * BT Message response format :
+ *
+ *    Byte 1  Byte 2     Byte 3  Byte 4  Byte 5  Byte 6:N
+ *    Length  NetFn/LUN  Seq     Cmd     Code    Data
+ */
+static ssize_t bt_bmc_write(struct file *file, const char __user *buf,
+                           size_t count, loff_t *ppos)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+       u8 kbuffer[BT_BMC_BUFFER_SIZE];
+       ssize_t ret = 0;
+       ssize_t nwritten;
+
+       /*
+        * send a minimum response size
+        */
+       if (count < 5)
+               return -EINVAL;
+
+       if (!access_ok(VERIFY_READ, buf, count))
+               return -EFAULT;
+
+       WARN_ON(*ppos);
+
+       /*
+        * There's no interrupt for clearing bmc busy so we have to
+        * poll
+        */
+       if (wait_event_interruptible(bt_bmc->queue,
+                                    !(bt_inb(bt_bmc, BT_CTRL) &
+                                      (BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN))))
+               return -ERESTARTSYS;
+
+       mutex_lock(&bt_bmc->mutex);
+
+       if (unlikely(bt_inb(bt_bmc, BT_CTRL) &
+                    (BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN))) {
+               ret = -EIO;
+               goto out_unlock;
+       }
+
+       clr_wr_ptr(bt_bmc);
+
+       while (count) {
+               nwritten = min_t(ssize_t, count, sizeof(kbuffer));
+               if (copy_from_user(&kbuffer, buf, nwritten)) {
+                       ret = -EFAULT;
+                       break;
+               }
+
+               bt_writen(bt_bmc, kbuffer, nwritten);
+
+               count -= nwritten;
+               buf += nwritten;
+               ret += nwritten;
+       }
+
+       set_b2h_atn(bt_bmc);
+
+out_unlock:
+       mutex_unlock(&bt_bmc->mutex);
+       return ret;
+}
+
+static long bt_bmc_ioctl(struct file *file, unsigned int cmd,
+                        unsigned long param)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+
+       switch (cmd) {
+       case BT_BMC_IOCTL_SMS_ATN:
+               set_sms_atn(bt_bmc);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int bt_bmc_release(struct inode *inode, struct file *file)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+
+       atomic_dec(&open_count);
+       set_b_busy(bt_bmc);
+       return 0;
+}
+
+static unsigned int bt_bmc_poll(struct file *file, poll_table *wait)
+{
+       struct bt_bmc *bt_bmc = file_bt_bmc(file);
+       unsigned int mask = 0;
+       u8 ctrl;
+
+       poll_wait(file, &bt_bmc->queue, wait);
+
+       ctrl = bt_inb(bt_bmc, BT_CTRL);
+
+       if (ctrl & BT_CTRL_H2B_ATN)
+               mask |= POLLIN;
+
+       if (!(ctrl & (BT_CTRL_H_BUSY | BT_CTRL_B2H_ATN)))
+               mask |= POLLOUT;
+
+       return mask;
+}
+
+static const struct file_operations bt_bmc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = bt_bmc_open,
+       .read           = bt_bmc_read,
+       .write          = bt_bmc_write,
+       .release        = bt_bmc_release,
+       .poll           = bt_bmc_poll,
+       .unlocked_ioctl = bt_bmc_ioctl,
+};
+
+static void poll_timer(unsigned long data)
+{
+       struct bt_bmc *bt_bmc = (void *)data;
+
+       bt_bmc->poll_timer.expires += msecs_to_jiffies(500);
+       wake_up(&bt_bmc->queue);
+       add_timer(&bt_bmc->poll_timer);
+}
+
+static irqreturn_t bt_bmc_irq(int irq, void *arg)
+{
+       struct bt_bmc *bt_bmc = arg;
+       u32 reg;
+
+       reg = ioread32(bt_bmc->base + BT_CR2);
+       reg &= BT_CR2_IRQ_H2B | BT_CR2_IRQ_HBUSY;
+       if (!reg)
+               return IRQ_NONE;
+
+       /* ack pending IRQs */
+       iowrite32(reg, bt_bmc->base + BT_CR2);
+
+       wake_up(&bt_bmc->queue);
+       return IRQ_HANDLED;
+}
+
+static int bt_bmc_config_irq(struct bt_bmc *bt_bmc,
+                            struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       u32 reg;
+       int rc;
+
+       bt_bmc->irq = platform_get_irq(pdev, 0);
+       if (!bt_bmc->irq)
+               return -ENODEV;
+
+       rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
+                             DEVICE_NAME, bt_bmc);
+       if (rc < 0) {
+               dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
+               bt_bmc->irq = 0;
+               return rc;
+       }
+
+       /*
+        * Configure IRQs on the bmc clearing the H2B and HBUSY bits;
+        * H2B will be asserted when the bmc has data for us; HBUSY
+        * will be cleared (along with B2H) when we can write the next
+        * message to the BT buffer
+        */
+       reg = ioread32(bt_bmc->base + BT_CR1);
+       reg |= BT_CR1_IRQ_H2B | BT_CR1_IRQ_HBUSY;
+       iowrite32(reg, bt_bmc->base + BT_CR1);
+
+       return 0;
+}
+
+static int bt_bmc_probe(struct platform_device *pdev)
+{
+       struct bt_bmc *bt_bmc;
+       struct device *dev;
+       struct resource *res;
+       int rc;
+
+       if (!pdev || !pdev->dev.of_node)
+               return -ENODEV;
+
+       dev = &pdev->dev;
+       dev_info(dev, "Found bt bmc device\n");
+
+       bt_bmc = devm_kzalloc(dev, sizeof(*bt_bmc), GFP_KERNEL);
+       if (!bt_bmc)
+               return -ENOMEM;
+
+       dev_set_drvdata(&pdev->dev, bt_bmc);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       bt_bmc->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(bt_bmc->base))
+               return PTR_ERR(bt_bmc->base);
+
+       mutex_init(&bt_bmc->mutex);
+       init_waitqueue_head(&bt_bmc->queue);
+
+       bt_bmc->miscdev.minor   = MISC_DYNAMIC_MINOR,
+               bt_bmc->miscdev.name    = DEVICE_NAME,
+               bt_bmc->miscdev.fops    = &bt_bmc_fops,
+               bt_bmc->miscdev.parent = dev;
+       rc = misc_register(&bt_bmc->miscdev);
+       if (rc) {
+               dev_err(dev, "Unable to register misc device\n");
+               return rc;
+       }
+
+       bt_bmc_config_irq(bt_bmc, pdev);
+
+       if (bt_bmc->irq) {
+               dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
+       } else {
+               dev_info(dev, "No IRQ; using timer\n");
+               setup_timer(&bt_bmc->poll_timer, poll_timer,
+                           (unsigned long)bt_bmc);
+               bt_bmc->poll_timer.expires = jiffies + msecs_to_jiffies(10);
+               add_timer(&bt_bmc->poll_timer);
+       }
+
+       iowrite32((BT_IO_BASE << BT_CR0_IO_BASE) |
+                 (BT_IRQ << BT_CR0_IRQ) |
+                 BT_CR0_EN_CLR_SLV_RDP |
+                 BT_CR0_EN_CLR_SLV_WRP |
+                 BT_CR0_ENABLE_IBT,
+                 bt_bmc->base + BT_CR0);
+
+       clr_b_busy(bt_bmc);
+
+       return 0;
+}
+
+static int bt_bmc_remove(struct platform_device *pdev)
+{
+       struct bt_bmc *bt_bmc = dev_get_drvdata(&pdev->dev);
+
+       misc_deregister(&bt_bmc->miscdev);
+       if (!bt_bmc->irq)
+               del_timer_sync(&bt_bmc->poll_timer);
+       return 0;
+}
+
+static const struct of_device_id bt_bmc_match[] = {
+       { .compatible = "aspeed,ast2400-bt-bmc" },
+       { },
+};
+
+static struct platform_driver bt_bmc_driver = {
+       .driver = {
+               .name           = DEVICE_NAME,
+               .of_match_table = bt_bmc_match,
+       },
+       .probe = bt_bmc_probe,
+       .remove = bt_bmc_remove,
+};
+
+module_platform_driver(bt_bmc_driver);
+
+MODULE_DEVICE_TABLE(of, bt_bmc_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alistair Popple <alistair@popple.id.au>");
+MODULE_DESCRIPTION("Linux device interface to the BT interface");
index d861999..fcdd886 100644 (file)
@@ -2891,11 +2891,11 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
                intf->curr_channel = IPMI_MAX_CHANNELS;
        }
 
+       rv = ipmi_bmc_register(intf, i);
+
        if (rv == 0)
                rv = add_proc_entries(intf, i);
 
-       rv = ipmi_bmc_register(intf, i);
-
  out:
        if (rv) {
                if (intf->proc_dir)
@@ -2982,8 +2982,6 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
        int intf_num = intf->intf_num;
        ipmi_user_t user;
 
-       ipmi_bmc_unregister(intf);
-
        mutex_lock(&smi_watchers_mutex);
        mutex_lock(&ipmi_interfaces_mutex);
        intf->intf_num = -1;
@@ -3007,6 +3005,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
        mutex_unlock(&ipmi_interfaces_mutex);
 
        remove_proc_entries(intf);
+       ipmi_bmc_unregister(intf);
 
        /*
         * Call all the watcher interfaces to tell them that
index 8de6187..3a9149c 100644 (file)
@@ -813,9 +813,6 @@ int tpm_do_selftest(struct tpm_chip *chip)
                        continue;
                }
 
-               if (rc < TPM_HEADER_SIZE)
-                       return -EFAULT;
-
                if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
                        dev_info(&chip->dev,
                                 "TPM is disabled/deactivated (0x%X)\n", rc);
index 190122e..85a449c 100644 (file)
@@ -203,7 +203,7 @@ at91_clk_register_programmable(struct regmap *regmap,
        ret = clk_hw_register(NULL, &prog->hw);
        if (ret) {
                kfree(prog);
-               hw = &prog->hw;
+               hw = ERR_PTR(ret);
        }
 
        return hw;
index b68bf57..8c7763f 100644 (file)
@@ -502,8 +502,12 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
 static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                                   unsigned long *parent_rate)
 {
+       struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+       const struct bcm2835_pll_data *data = pll->data;
        u32 ndiv, fdiv;
 
+       rate = clamp(rate, data->min_rate, data->max_rate);
+
        bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
 
        return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
@@ -608,13 +612,6 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
        u32 ana[4];
        int i;
 
-       if (rate < data->min_rate || rate > data->max_rate) {
-               dev_err(cprman->dev, "%s: rate out of spec: %lu vs (%lu, %lu)\n",
-                       clk_hw_get_name(hw), rate,
-                       data->min_rate, data->max_rate);
-               return -EINVAL;
-       }
-
        if (rate > data->max_fb_rate) {
                use_fb_prediv = true;
                rate /= 2;
index b637f59..eb953d3 100644 (file)
@@ -216,6 +216,7 @@ static int max77686_clk_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       drv_data->num_clks = num_clks;
        drv_data->max_clk_data = devm_kcalloc(dev, num_clks,
                                              sizeof(*drv_data->max_clk_data),
                                              GFP_KERNEL);
index fe364e6..c0e8e1f 100644 (file)
@@ -195,7 +195,7 @@ static void __init hi6220_clk_sys_init(struct device_node *np)
        hi6220_clk_register_divider(hi6220_div_clks_sys,
                        ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
 }
-CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
+CLK_OF_DECLARE_DRIVER(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
 
 
 /* clocks in media controller */
@@ -252,7 +252,7 @@ static void __init hi6220_clk_media_init(struct device_node *np)
        hi6220_clk_register_divider(hi6220_div_clks_media,
                                ARRAY_SIZE(hi6220_div_clks_media), clk_data);
 }
-CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
+CLK_OF_DECLARE_DRIVER(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
 
 
 /* clocks in pmctrl */
index 380c372..f042bd2 100644 (file)
@@ -8,6 +8,7 @@ config COMMON_CLK_MEDIATEK
 
 config COMMON_CLK_MT8135
        bool "Clock driver for Mediatek MT8135"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
        select COMMON_CLK_MEDIATEK
        default ARCH_MEDIATEK
        ---help---
@@ -15,6 +16,7 @@ config COMMON_CLK_MT8135
 
 config COMMON_CLK_MT8173
        bool "Clock driver for Mediatek MT8173"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
        select COMMON_CLK_MEDIATEK
        default ARCH_MEDIATEK
        ---help---
index 45905fc..cecb0fd 100644 (file)
@@ -305,7 +305,7 @@ static const struct of_device_id armada_3700_periph_clock_of_match[] = {
 };
 static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
                                         void __iomem *reg, spinlock_t *lock,
-                                        struct device *dev, struct clk_hw *hw)
+                                        struct device *dev, struct clk_hw **hw)
 {
        const struct clk_ops *mux_ops = NULL, *gate_ops = NULL,
                *rate_ops = NULL;
@@ -329,6 +329,7 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
                gate->lock = lock;
                gate_ops = gate_hw->init->ops;
                gate->reg = reg + (u64)gate->reg;
+               gate->flags = CLK_GATE_SET_TO_DISABLE;
        }
 
        if (data->rate_hw) {
@@ -353,13 +354,13 @@ static int armada_3700_add_composite_clk(const struct clk_periph_data *data,
                }
        }
 
-       hw = clk_hw_register_composite(dev, data->name, data->parent_names,
+       *hw = clk_hw_register_composite(dev, data->name, data->parent_names,
                                       data->num_parents, mux_hw,
                                       mux_ops, rate_hw, rate_ops,
                                       gate_hw, gate_ops, CLK_IGNORE_UNUSED);
 
-       if (IS_ERR(hw))
-               return PTR_ERR(hw);
+       if (IS_ERR(*hw))
+               return PTR_ERR(*hw);
 
        return 0;
 }
@@ -400,7 +401,7 @@ static int armada_3700_periph_clock_probe(struct platform_device *pdev)
        spin_lock_init(&driver_data->lock);
 
        for (i = 0; i < num_periph; i++) {
-               struct clk_hw *hw = driver_data->hw_data->hws[i];
+               struct clk_hw **hw = &driver_data->hw_data->hws[i];
 
                if (armada_3700_add_composite_clk(&data[i], reg,
                                                  &driver_data->lock, dev, hw))
index 51d152f..17e68a7 100644 (file)
@@ -106,6 +106,7 @@ static const struct of_device_id exynos_audss_clk_of_match[] = {
        },
        { },
 };
+MODULE_DEVICE_TABLE(of, exynos_audss_clk_of_match);
 
 static void exynos_audss_clk_teardown(void)
 {
index 5ffb898..26c53f7 100644 (file)
@@ -79,7 +79,7 @@ static int uniphier_clk_probe(struct platform_device *pdev)
        hw_data->num = clk_num;
 
        /* avoid returning NULL for unused idx */
-       for (; clk_num >= 0; clk_num--)
+       while (--clk_num >= 0)
                hw_data->hws[clk_num] = ERR_PTR(-EINVAL);
 
        for (p = data; p->name; p++) {
@@ -110,6 +110,10 @@ static int uniphier_clk_remove(struct platform_device *pdev)
 
 static const struct of_device_id uniphier_clk_match[] = {
        /* System clock */
+       {
+               .compatible = "socionext,uniphier-sld3-clock",
+               .data = uniphier_sld3_sys_clk_data,
+       },
        {
                .compatible = "socionext,uniphier-ld4-clock",
                .data = uniphier_ld4_sys_clk_data,
@@ -138,7 +142,7 @@ static const struct of_device_id uniphier_clk_match[] = {
                .compatible = "socionext,uniphier-ld20-clock",
                .data = uniphier_ld20_sys_clk_data,
        },
-       /* Media I/O clock */
+       /* Media I/O clock, SD clock */
        {
                .compatible = "socionext,uniphier-sld3-mio-clock",
                .data = uniphier_sld3_mio_clk_data,
@@ -156,20 +160,20 @@ static const struct of_device_id uniphier_clk_match[] = {
                .data = uniphier_sld3_mio_clk_data,
        },
        {
-               .compatible = "socionext,uniphier-pro5-mio-clock",
-               .data = uniphier_pro5_mio_clk_data,
+               .compatible = "socionext,uniphier-pro5-sd-clock",
+               .data = uniphier_pro5_sd_clk_data,
        },
        {
-               .compatible = "socionext,uniphier-pxs2-mio-clock",
-               .data = uniphier_pro5_mio_clk_data,
+               .compatible = "socionext,uniphier-pxs2-sd-clock",
+               .data = uniphier_pro5_sd_clk_data,
        },
        {
                .compatible = "socionext,uniphier-ld11-mio-clock",
                .data = uniphier_sld3_mio_clk_data,
        },
        {
-               .compatible = "socionext,uniphier-ld20-mio-clock",
-               .data = uniphier_pro5_mio_clk_data,
+               .compatible = "socionext,uniphier-ld20-sd-clock",
+               .data = uniphier_pro5_sd_clk_data,
        },
        /* Peripheral clock */
        {
index 6aa7ec7..218d20f 100644 (file)
@@ -93,7 +93,7 @@ const struct uniphier_clk_data uniphier_sld3_mio_clk_data[] = {
        { /* sentinel */ }
 };
 
-const struct uniphier_clk_data uniphier_pro5_mio_clk_data[] = {
+const struct uniphier_clk_data uniphier_pro5_sd_clk_data[] = {
        UNIPHIER_MIO_CLK_SD_FIXED,
        UNIPHIER_MIO_CLK_SD(0, 0),
        UNIPHIER_MIO_CLK_SD(1, 1),
index 15a2f2c..2c243a8 100644 (file)
@@ -42,7 +42,7 @@ static u8 uniphier_clk_mux_get_parent(struct clk_hw *hw)
        struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);
        int num_parents = clk_hw_get_num_parents(hw);
        int ret;
-       u32 val;
+       unsigned int val;
        u8 i;
 
        ret = regmap_read(mux->regmap, mux->reg, &val);
index 3ae1840..0244dba 100644 (file)
@@ -115,7 +115,7 @@ extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[];
 extern const struct uniphier_clk_data uniphier_ld11_sys_clk_data[];
 extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[];
 extern const struct uniphier_clk_data uniphier_sld3_mio_clk_data[];
-extern const struct uniphier_clk_data uniphier_pro5_mio_clk_data[];
+extern const struct uniphier_clk_data uniphier_pro5_sd_clk_data[];
 extern const struct uniphier_clk_data uniphier_ld4_peri_clk_data[];
 extern const struct uniphier_clk_data uniphier_pro4_peri_clk_data[];
 
index 2451908..e2c6e43 100644 (file)
@@ -417,6 +417,16 @@ config SYS_SUPPORTS_SH_TMU
 config SYS_SUPPORTS_EM_STI
         bool
 
+config CLKSRC_JCORE_PIT
+       bool "J-Core PIT timer driver" if COMPILE_TEST
+       depends on OF
+       depends on GENERIC_CLOCKEVENTS
+       depends on HAS_IOMEM
+       select CLKSRC_MMIO
+       help
+         This enables build of clocksource and clockevent driver for
+         the integrated PIT in the J-Core synthesizable, open source SoC.
+
 config SH_TIMER_CMT
        bool "Renesas CMT timer driver" if COMPILE_TEST
        depends on GENERIC_CLOCKEVENTS
index fd9d6df..cf87f40 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_ATMEL_TCB_CLKSRC)  += tcb_clksrc.o
 obj-$(CONFIG_X86_PM_TIMER)     += acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)   += scx200_hrt.o
 obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)   += cs5535-clockevt.o
+obj-$(CONFIG_CLKSRC_JCORE_PIT)         += jcore-pit.o
 obj-$(CONFIG_SH_TIMER_CMT)     += sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)    += sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)     += sh_tmu.o
diff --git a/drivers/clocksource/jcore-pit.c b/drivers/clocksource/jcore-pit.c
new file mode 100644 (file)
index 0000000..54e1665
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * J-Core SoC PIT/clocksource driver
+ *
+ * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/sched_clock.h>
+#include <linux/cpu.h>
+#include <linux/cpuhotplug.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define PIT_IRQ_SHIFT          12
+#define PIT_PRIO_SHIFT         20
+#define PIT_ENABLE_SHIFT       26
+#define PIT_PRIO_MASK          0xf
+
+#define REG_PITEN              0x00
+#define REG_THROT              0x10
+#define REG_COUNT              0x14
+#define REG_BUSPD              0x18
+#define REG_SECHI              0x20
+#define REG_SECLO              0x24
+#define REG_NSEC               0x28
+
+struct jcore_pit {
+       struct clock_event_device       ced;
+       void __iomem                    *base;
+       unsigned long                   periodic_delta;
+       u32                             enable_val;
+};
+
+static void __iomem *jcore_pit_base;
+static struct jcore_pit __percpu *jcore_pit_percpu;
+
+static notrace u64 jcore_sched_clock_read(void)
+{
+       u32 seclo, nsec, seclo0;
+       __iomem void *base = jcore_pit_base;
+
+       seclo = readl(base + REG_SECLO);
+       do {
+               seclo0 = seclo;
+               nsec  = readl(base + REG_NSEC);
+               seclo = readl(base + REG_SECLO);
+       } while (seclo0 != seclo);
+
+       return seclo * NSEC_PER_SEC + nsec;
+}
+
+static cycle_t jcore_clocksource_read(struct clocksource *cs)
+{
+       return jcore_sched_clock_read();
+}
+
+static int jcore_pit_disable(struct jcore_pit *pit)
+{
+       writel(0, pit->base + REG_PITEN);
+       return 0;
+}
+
+static int jcore_pit_set(unsigned long delta, struct jcore_pit *pit)
+{
+       jcore_pit_disable(pit);
+       writel(delta, pit->base + REG_THROT);
+       writel(pit->enable_val, pit->base + REG_PITEN);
+       return 0;
+}
+
+static int jcore_pit_set_state_shutdown(struct clock_event_device *ced)
+{
+       struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
+       return jcore_pit_disable(pit);
+}
+
+static int jcore_pit_set_state_oneshot(struct clock_event_device *ced)
+{
+       struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
+       return jcore_pit_disable(pit);
+}
+
+static int jcore_pit_set_state_periodic(struct clock_event_device *ced)
+{
+       struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
+       return jcore_pit_set(pit->periodic_delta, pit);
+}
+
+static int jcore_pit_set_next_event(unsigned long delta,
+                                   struct clock_event_device *ced)
+{
+       struct jcore_pit *pit = container_of(ced, struct jcore_pit, ced);
+
+       return jcore_pit_set(delta, pit);
+}
+
+static int jcore_pit_local_init(unsigned cpu)
+{
+       struct jcore_pit *pit = this_cpu_ptr(jcore_pit_percpu);
+       unsigned buspd, freq;
+
+       pr_info("Local J-Core PIT init on cpu %u\n", cpu);
+
+       buspd = readl(pit->base + REG_BUSPD);
+       freq = DIV_ROUND_CLOSEST(NSEC_PER_SEC, buspd);
+       pit->periodic_delta = DIV_ROUND_CLOSEST(NSEC_PER_SEC, HZ * buspd);
+
+       clockevents_config_and_register(&pit->ced, freq, 1, ULONG_MAX);
+
+       return 0;
+}
+
+static irqreturn_t jcore_timer_interrupt(int irq, void *dev_id)
+{
+       struct jcore_pit *pit = this_cpu_ptr(dev_id);
+
+       if (clockevent_state_oneshot(&pit->ced))
+               jcore_pit_disable(pit);
+
+       pit->ced.event_handler(&pit->ced);
+
+       return IRQ_HANDLED;
+}
+
+static int __init jcore_pit_init(struct device_node *node)
+{
+       int err;
+       unsigned pit_irq, cpu;
+       unsigned long hwirq;
+       u32 irqprio, enable_val;
+
+       jcore_pit_base = of_iomap(node, 0);
+       if (!jcore_pit_base) {
+               pr_err("Error: Cannot map base address for J-Core PIT\n");
+               return -ENXIO;
+       }
+
+       pit_irq = irq_of_parse_and_map(node, 0);
+       if (!pit_irq) {
+               pr_err("Error: J-Core PIT has no IRQ\n");
+               return -ENXIO;
+       }
+
+       pr_info("Initializing J-Core PIT at %p IRQ %d\n",
+               jcore_pit_base, pit_irq);
+
+       err = clocksource_mmio_init(jcore_pit_base, "jcore_pit_cs",
+                                   NSEC_PER_SEC, 400, 32,
+                                   jcore_clocksource_read);
+       if (err) {
+               pr_err("Error registering clocksource device: %d\n", err);
+               return err;
+       }
+
+       sched_clock_register(jcore_sched_clock_read, 32, NSEC_PER_SEC);
+
+       jcore_pit_percpu = alloc_percpu(struct jcore_pit);
+       if (!jcore_pit_percpu) {
+               pr_err("Failed to allocate memory for clock event device\n");
+               return -ENOMEM;
+       }
+
+       err = request_irq(pit_irq, jcore_timer_interrupt,
+                         IRQF_TIMER | IRQF_PERCPU,
+                         "jcore_pit", jcore_pit_percpu);
+       if (err) {
+               pr_err("pit irq request failed: %d\n", err);
+               free_percpu(jcore_pit_percpu);
+               return err;
+       }
+
+       /*
+        * The J-Core PIT is not hard-wired to a particular IRQ, but
+        * integrated with the interrupt controller such that the IRQ it
+        * generates is programmable, as follows:
+        *
+        * The bit layout of the PIT enable register is:
+        *
+        *      .....e..ppppiiiiiiii............
+        *
+        * where the .'s indicate unrelated/unused bits, e is enable,
+        * p is priority, and i is hard irq number.
+        *
+        * For the PIT included in AIC1 (obsolete but still in use),
+        * any hard irq (trap number) can be programmed via the 8
+        * iiiiiiii bits, and a priority (0-15) is programmable
+        * separately in the pppp bits.
+        *
+        * For the PIT included in AIC2 (current), the programming
+        * interface is equivalent modulo interrupt mapping. This is
+        * why a different compatible tag was not used. However only
+        * traps 64-127 (the ones actually intended to be used for
+        * interrupts, rather than syscalls/exceptions/etc.) can be
+        * programmed (the high 2 bits of i are ignored) and the
+        * priority pppp is <<2'd and or'd onto the irq number. This
+        * choice seems to have been made on the hardware engineering
+        * side under an assumption that preserving old AIC1 priority
+        * mappings was important. Future models will likely ignore
+        * the pppp field.
+        */
+       hwirq = irq_get_irq_data(pit_irq)->hwirq;
+       irqprio = (hwirq >> 2) & PIT_PRIO_MASK;
+       enable_val = (1U << PIT_ENABLE_SHIFT)
+                  | (hwirq << PIT_IRQ_SHIFT)
+                  | (irqprio << PIT_PRIO_SHIFT);
+
+       for_each_present_cpu(cpu) {
+               struct jcore_pit *pit = per_cpu_ptr(jcore_pit_percpu, cpu);
+
+               pit->base = of_iomap(node, cpu);
+               if (!pit->base) {
+                       pr_err("Unable to map PIT for cpu %u\n", cpu);
+                       continue;
+               }
+
+               pit->ced.name = "jcore_pit";
+               pit->ced.features = CLOCK_EVT_FEAT_PERIODIC
+                                 | CLOCK_EVT_FEAT_ONESHOT
+                                 | CLOCK_EVT_FEAT_PERCPU;
+               pit->ced.cpumask = cpumask_of(cpu);
+               pit->ced.rating = 400;
+               pit->ced.irq = pit_irq;
+               pit->ced.set_state_shutdown = jcore_pit_set_state_shutdown;
+               pit->ced.set_state_periodic = jcore_pit_set_state_periodic;
+               pit->ced.set_state_oneshot = jcore_pit_set_state_oneshot;
+               pit->ced.set_next_event = jcore_pit_set_next_event;
+
+               pit->enable_val = enable_val;
+       }
+
+       cpuhp_setup_state(CPUHP_AP_JCORE_TIMER_STARTING,
+                         "AP_JCORE_TIMER_STARTING",
+                         jcore_pit_local_init, NULL);
+
+       return 0;
+}
+
+CLOCKSOURCE_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
index c184eb8..4f87f3e 100644 (file)
@@ -152,6 +152,13 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static cycle_t sun5i_clksrc_read(struct clocksource *clksrc)
+{
+       struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
+
+       return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
+}
+
 static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
                                unsigned long event, void *data)
 {
@@ -210,8 +217,13 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
        writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
               base + TIMER_CTL_REG(1));
 
-       ret = clocksource_mmio_init(base + TIMER_CNTVAL_LO_REG(1), node->name,
-                                   rate, 340, 32, clocksource_mmio_readl_down);
+       cs->clksrc.name = node->name;
+       cs->clksrc.rating = 340;
+       cs->clksrc.read = sun5i_clksrc_read;
+       cs->clksrc.mask = CLOCKSOURCE_MASK(32);
+       cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+       ret = clocksource_register_hz(&cs->clksrc, rate);
        if (ret) {
                pr_err("Couldn't register clock source.\n");
                goto err_remove_notifier;
index f535f81..4737520 100644 (file)
@@ -179,6 +179,7 @@ struct _pid {
 /**
  * struct cpudata -    Per CPU instance data storage
  * @cpu:               CPU number for this instance data
+ * @policy:            CPUFreq policy value
  * @update_util:       CPUFreq utility callback information
  * @update_util_set:   CPUFreq utility callback is set
  * @iowait_boost:      iowait-related boost fraction
@@ -201,6 +202,7 @@ struct _pid {
 struct cpudata {
        int cpu;
 
+       unsigned int policy;
        struct update_util_data update_util;
        bool   update_util_set;
 
@@ -1142,10 +1144,8 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
        *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
 }
 
-static void intel_pstate_set_min_pstate(struct cpudata *cpu)
+static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
 {
-       int pstate = cpu->pstate.min_pstate;
-
        trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
        cpu->pstate.current_pstate = pstate;
        /*
@@ -1157,6 +1157,20 @@ static void intel_pstate_set_min_pstate(struct cpudata *cpu)
                      pstate_funcs.get_val(cpu, pstate));
 }
 
+static void intel_pstate_set_min_pstate(struct cpudata *cpu)
+{
+       intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
+}
+
+static void intel_pstate_max_within_limits(struct cpudata *cpu)
+{
+       int min_pstate, max_pstate;
+
+       update_turbo_state();
+       intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate);
+       intel_pstate_set_pstate(cpu, max_pstate);
+}
+
 static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 {
        cpu->pstate.min_pstate = pstate_funcs.get_min();
@@ -1325,7 +1339,8 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
 
        from = cpu->pstate.current_pstate;
 
-       target_pstate = pstate_funcs.get_target_pstate(cpu);
+       target_pstate = cpu->policy == CPUFREQ_POLICY_PERFORMANCE ?
+               cpu->pstate.turbo_pstate : pstate_funcs.get_target_pstate(cpu);
 
        intel_pstate_update_pstate(cpu, target_pstate);
 
@@ -1491,7 +1506,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        pr_debug("set_policy cpuinfo.max %u policy->max %u\n",
                 policy->cpuinfo.max_freq, policy->max);
 
-       cpu = all_cpu_data[0];
+       cpu = all_cpu_data[policy->cpu];
+       cpu->policy = policy->policy;
+
        if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
            policy->max < policy->cpuinfo.max_freq &&
            policy->max > cpu->pstate.max_pstate * cpu->pstate.scaling) {
@@ -1499,7 +1516,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                policy->max = policy->cpuinfo.max_freq;
        }
 
-       if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+       if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
                limits = &performance_limits;
                if (policy->max >= policy->cpuinfo.max_freq) {
                        pr_debug("set performance\n");
@@ -1535,6 +1552,15 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
  out:
+       if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
+               /*
+                * NOHZ_FULL CPUs need this as the governor callback may not
+                * be invoked on them.
+                */
+               intel_pstate_clear_update_util_hook(policy->cpu);
+               intel_pstate_max_within_limits(cpu);
+       }
+
        intel_pstate_set_update_util_hook(policy->cpu);
 
        intel_pstate_hwp_set_policy(policy);
index daadd20..3e2ab3b 100644 (file)
@@ -14,7 +14,7 @@ if DEV_DAX
 
 config DEV_DAX_PMEM
        tristate "PMEM DAX: direct access to persistent memory"
-       depends on NVDIMM_DAX
+       depends on LIBNVDIMM && NVDIMM_DAX
        default DEV_DAX
        help
          Support raw access to persistent memory.  Note that this
index 9630d88..4a15fa5 100644 (file)
@@ -44,7 +44,6 @@ static void dax_pmem_percpu_exit(void *data)
 
        dev_dbg(dax_pmem->dev, "%s\n", __func__);
        percpu_ref_exit(ref);
-       wait_for_completion(&dax_pmem->cmp);
 }
 
 static void dax_pmem_percpu_kill(void *data)
@@ -54,6 +53,7 @@ static void dax_pmem_percpu_kill(void *data)
 
        dev_dbg(dax_pmem->dev, "%s\n", __func__);
        percpu_ref_kill(ref);
+       wait_for_completion(&dax_pmem->cmp);
 }
 
 static int dax_pmem_probe(struct device *dev)
index ca957a5..b8cde09 100644 (file)
@@ -51,7 +51,7 @@ static void qcom_usb_extcon_detect_cable(struct work_struct *work)
        if (ret)
                return;
 
-       extcon_set_state(info->edev, EXTCON_USB_HOST, !id);
+       extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id);
 }
 
 static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id)
index 631c977..180f0a9 100644 (file)
@@ -566,6 +566,11 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
 
        lynx->registers = ioremap_nocache(pci_resource_start(dev, 0),
                                          PCILYNX_MAX_REGISTER);
+       if (lynx->registers == NULL) {
+               dev_err(&dev->dev, "Failed to map registers\n");
+               ret = -ENOMEM;
+               goto fail_deallocate_lynx;
+       }
 
        lynx->rcv_start_pcl = pci_alloc_consistent(lynx->pci_device,
                                sizeof(struct pcl), &lynx->rcv_start_pcl_bus);
@@ -578,7 +583,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
            lynx->rcv_buffer == NULL) {
                dev_err(&dev->dev, "Failed to allocate receive buffer\n");
                ret = -ENOMEM;
-               goto fail_deallocate;
+               goto fail_deallocate_buffers;
        }
        lynx->rcv_start_pcl->next       = cpu_to_le32(lynx->rcv_pcl_bus);
        lynx->rcv_pcl->next             = cpu_to_le32(PCL_NEXT_INVALID);
@@ -641,7 +646,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused)
                dev_err(&dev->dev,
                        "Failed to allocate shared interrupt %d\n", dev->irq);
                ret = -EIO;
-               goto fail_deallocate;
+               goto fail_deallocate_buffers;
        }
 
        lynx->misc.parent = &dev->dev;
@@ -668,7 +673,7 @@ fail_free_irq:
        reg_write(lynx, PCI_INT_ENABLE, 0);
        free_irq(lynx->pci_device->irq, lynx);
 
-fail_deallocate:
+fail_deallocate_buffers:
        if (lynx->rcv_start_pcl)
                pci_free_consistent(lynx->pci_device, sizeof(struct pcl),
                                lynx->rcv_start_pcl, lynx->rcv_start_pcl_bus);
@@ -679,6 +684,8 @@ fail_deallocate:
                pci_free_consistent(lynx->pci_device, PAGE_SIZE,
                                lynx->rcv_buffer, lynx->rcv_buffer_bus);
        iounmap(lynx->registers);
+
+fail_deallocate_lynx:
        kfree(lynx);
 
 fail_disable:
index c069451..5e23e2d 100644 (file)
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86)          += -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
                                   -mno-mmx -mno-sse
 
 cflags-$(CONFIG_ARM64)         := $(subst -pg,,$(KBUILD_CFLAGS))
-cflags-$(CONFIG_ARM)           := $(subst -pg,,$(KBUILD_CFLAGS)) \
+cflags-$(CONFIG_ARM)           := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \
                                   -fno-builtin -fpic -mno-single-pic-base
 
 cflags-$(CONFIG_EFI_ARMSTUB)   += -I$(srctree)/scripts/dtc/libfdt
@@ -79,5 +79,6 @@ quiet_cmd_stubcopy = STUBCPY $@
 # decompressor. So move our .data to .data.efistub, which is preserved
 # explicitly by the decompressor linker script.
 #
-STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub
+STUBCOPY_FLAGS-$(CONFIG_ARM)   += --rename-section .data=.data.efistub \
+                                  -R ___ksymtab+sort -R ___kcrctab+sort
 STUBCOPY_RELOC-$(CONFIG_ARM)   := R_ARM_ABS
index 26ee00f..d011cb8 100644 (file)
@@ -284,7 +284,7 @@ config GPIO_MM_LANTIQ
 
 config GPIO_MOCKUP
        tristate "GPIO Testing Driver"
-       depends on GPIOLIB
+       depends on GPIOLIB && SYSFS
        select GPIO_SYSFS
        help
          This enables GPIO Testing driver, which provides a way to test GPIO
index 9457e20..dc37dbe 100644 (file)
@@ -219,6 +219,7 @@ static const struct of_device_id ath79_gpio_of_match[] = {
        { .compatible = "qca,ar9340-gpio" },
        {},
 };
+MODULE_DEVICE_TABLE(of, ath79_gpio_of_match);
 
 static int ath79_gpio_probe(struct platform_device *pdev)
 {
index 425501c..793518a 100644 (file)
@@ -239,7 +239,7 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
                                irq_hw_number_t hwirq)
 {
        irq_set_chip_data(irq, h->host_data);
-       irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
+       irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_edge_irq);
 
        return 0;
 }
index b9daa0b..ee17248 100644 (file)
@@ -308,8 +308,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
 
        irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
-       if (irq_base < 0)
-               return irq_base;
+       if (irq_base < 0) {
+               err = irq_base;
+               goto out_iounmap;
+       }
 
        port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
                                             &irq_domain_simple_ops, NULL);
@@ -349,6 +351,8 @@ out_irqdomain_remove:
        irq_domain_remove(port->domain);
 out_irqdesc_free:
        irq_free_descs(irq_base, 32);
+out_iounmap:
+       iounmap(port->base);
        return err;
 }
 
index e7d422a..5b00427 100644 (file)
@@ -409,7 +409,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
                 * 801/1801/1600, bits are cleared when read.
                 * Edge detect register is not present on 801/1600/1801
                 */
-               if (stmpe->partnum != STMPE801 || stmpe->partnum != STMPE1600 ||
+               if (stmpe->partnum != STMPE801 && stmpe->partnum != STMPE1600 &&
                    stmpe->partnum != STMPE1801) {
                        stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
                        stmpe_reg_write(stmpe,
index 9925611..c2a80b4 100644 (file)
@@ -66,6 +66,7 @@ static const struct of_device_id ts4800_gpio_of_match[] = {
        { .compatible = "technologic,ts4800-gpio", },
        {},
 };
+MODULE_DEVICE_TABLE(of, ts4800_gpio_of_match);
 
 static struct platform_driver ts4800_gpio_driver = {
        .driver = {
index 58ece20..72a4b32 100644 (file)
@@ -653,14 +653,17 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
        int idx, i;
        unsigned int irq_flags;
+       int ret = -ENOENT;
 
        for (i = 0, idx = 0; idx <= index; i++) {
                struct acpi_gpio_info info;
                struct gpio_desc *desc;
 
                desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
-               if (IS_ERR(desc))
+               if (IS_ERR(desc)) {
+                       ret = PTR_ERR(desc);
                        break;
+               }
                if (info.gpioint && idx++ == index) {
                        int irq = gpiod_to_irq(desc);
 
@@ -679,7 +682,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
                }
 
        }
-       return -ENOENT;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
 
index f0fc3a0..20e09b7 100644 (file)
@@ -333,6 +333,13 @@ struct linehandle_state {
        u32 numdescs;
 };
 
+#define GPIOHANDLE_REQUEST_VALID_FLAGS \
+       (GPIOHANDLE_REQUEST_INPUT | \
+       GPIOHANDLE_REQUEST_OUTPUT | \
+       GPIOHANDLE_REQUEST_ACTIVE_LOW | \
+       GPIOHANDLE_REQUEST_OPEN_DRAIN | \
+       GPIOHANDLE_REQUEST_OPEN_SOURCE)
+
 static long linehandle_ioctl(struct file *filep, unsigned int cmd,
                             unsigned long arg)
 {
@@ -344,6 +351,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
        if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
                int val;
 
+               memset(&ghd, 0, sizeof(ghd));
+
                /* TODO: check if descriptors are really input */
                for (i = 0; i < lh->numdescs; i++) {
                        val = gpiod_get_value_cansleep(lh->descs[i]);
@@ -444,6 +453,17 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                u32 lflags = handlereq.flags;
                struct gpio_desc *desc;
 
+               if (offset >= gdev->ngpio) {
+                       ret = -EINVAL;
+                       goto out_free_descs;
+               }
+
+               /* Return an error if a unknown flag is set */
+               if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) {
+                       ret = -EINVAL;
+                       goto out_free_descs;
+               }
+
                desc = &gdev->descs[offset];
                ret = gpiod_request(desc, lh->label);
                if (ret)
@@ -536,6 +556,10 @@ struct lineevent_state {
        struct mutex read_lock;
 };
 
+#define GPIOEVENT_REQUEST_VALID_FLAGS \
+       (GPIOEVENT_REQUEST_RISING_EDGE | \
+       GPIOEVENT_REQUEST_FALLING_EDGE)
+
 static unsigned int lineevent_poll(struct file *filep,
                                   struct poll_table_struct *wait)
 {
@@ -623,6 +647,8 @@ static long lineevent_ioctl(struct file *filep, unsigned int cmd,
        if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
                int val;
 
+               memset(&ghd, 0, sizeof(ghd));
+
                val = gpiod_get_value_cansleep(le->desc);
                if (val < 0)
                        return val;
@@ -726,6 +752,18 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        lflags = eventreq.handleflags;
        eflags = eventreq.eventflags;
 
+       if (offset >= gdev->ngpio) {
+               ret = -EINVAL;
+               goto out_free_label;
+       }
+
+       /* Return an error if a unknown flag is set */
+       if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
+           (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS)) {
+               ret = -EINVAL;
+               goto out_free_label;
+       }
+
        /* This is just wrong: we don't look for events on output lines */
        if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
                ret = -EINVAL;
@@ -823,6 +861,8 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
                struct gpiochip_info chipinfo;
 
+               memset(&chipinfo, 0, sizeof(chipinfo));
+
                strncpy(chipinfo.name, dev_name(&gdev->dev),
                        sizeof(chipinfo.name));
                chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
@@ -839,7 +879,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
                if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
                        return -EFAULT;
-               if (lineinfo.line_offset > gdev->ngpio)
+               if (lineinfo.line_offset >= gdev->ngpio)
                        return -EINVAL;
 
                desc = &gdev->descs[lineinfo.line_offset];
index 2e3a054..e3281d4 100644 (file)
@@ -765,7 +765,7 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)
        return ret;
 }
 
-static void amdgpu_connector_destroy(struct drm_connector *connector)
+static void amdgpu_connector_unregister(struct drm_connector *connector)
 {
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
@@ -773,6 +773,12 @@ static void amdgpu_connector_destroy(struct drm_connector *connector)
                drm_dp_aux_unregister(&amdgpu_connector->ddc_bus->aux);
                amdgpu_connector->ddc_bus->has_aux = false;
        }
+}
+
+static void amdgpu_connector_destroy(struct drm_connector *connector)
+{
+       struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+
        amdgpu_connector_free_edid(connector);
        kfree(amdgpu_connector->con_priv);
        drm_connector_unregister(connector);
@@ -826,6 +832,7 @@ static const struct drm_connector_funcs amdgpu_connector_lvds_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = amdgpu_connector_lvds_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .early_unregister = amdgpu_connector_unregister,
        .destroy = amdgpu_connector_destroy,
        .set_property = amdgpu_connector_set_lcd_property,
 };
@@ -936,6 +943,7 @@ static const struct drm_connector_funcs amdgpu_connector_vga_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = amdgpu_connector_vga_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .early_unregister = amdgpu_connector_unregister,
        .destroy = amdgpu_connector_destroy,
        .set_property = amdgpu_connector_set_property,
 };
@@ -1203,6 +1211,7 @@ static const struct drm_connector_funcs amdgpu_connector_dvi_funcs = {
        .detect = amdgpu_connector_dvi_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = amdgpu_connector_set_property,
+       .early_unregister = amdgpu_connector_unregister,
        .destroy = amdgpu_connector_destroy,
        .force = amdgpu_connector_dvi_force,
 };
@@ -1493,6 +1502,7 @@ static const struct drm_connector_funcs amdgpu_connector_dp_funcs = {
        .detect = amdgpu_connector_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = amdgpu_connector_set_property,
+       .early_unregister = amdgpu_connector_unregister,
        .destroy = amdgpu_connector_destroy,
        .force = amdgpu_connector_dvi_force,
 };
@@ -1502,6 +1512,7 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {
        .detect = amdgpu_connector_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = amdgpu_connector_set_lcd_property,
+       .early_unregister = amdgpu_connector_unregister,
        .destroy = amdgpu_connector_destroy,
        .force = amdgpu_connector_dvi_force,
 };
index e203e55..a5e2fcb 100644 (file)
@@ -43,6 +43,9 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx)
                ctx->rings[i].sequence = 1;
                ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i];
        }
+
+       ctx->reset_counter = atomic_read(&adev->gpu_reset_counter);
+
        /* create context entity for each ring */
        for (i = 0; i < adev->num_rings; i++) {
                struct amdgpu_ring *ring = adev->rings[i];
index 7dbe85d..b4f4a92 100644 (file)
@@ -1408,16 +1408,6 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
        for (i = 0; i < adev->num_ip_blocks; i++) {
                if (!adev->ip_block_status[i].valid)
                        continue;
-               if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_UVD ||
-                       adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_VCE)
-                       continue;
-               /* enable clockgating to save power */
-               r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-                                                                   AMD_CG_STATE_GATE);
-               if (r) {
-                       DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
-                       return r;
-               }
                if (adev->ip_blocks[i].funcs->late_init) {
                        r = adev->ip_blocks[i].funcs->late_init((void *)adev);
                        if (r) {
@@ -1426,6 +1416,18 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
                        }
                        adev->ip_block_status[i].late_initialized = true;
                }
+               /* skip CG for VCE/UVD, it's handled specially */
+               if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD &&
+                   adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) {
+                       /* enable clockgating to save power */
+                       r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
+                                                                           AMD_CG_STATE_GATE);
+                       if (r) {
+                               DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n",
+                                         adev->ip_blocks[i].funcs->name, r);
+                               return r;
+                       }
+               }
        }
 
        return 0;
@@ -1435,6 +1437,30 @@ static int amdgpu_fini(struct amdgpu_device *adev)
 {
        int i, r;
 
+       /* need to disable SMC first */
+       for (i = 0; i < adev->num_ip_blocks; i++) {
+               if (!adev->ip_block_status[i].hw)
+                       continue;
+               if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) {
+                       /* ungate blocks before hw fini so that we can shutdown the blocks safely */
+                       r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
+                                                                           AMD_CG_STATE_UNGATE);
+                       if (r) {
+                               DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
+                                         adev->ip_blocks[i].funcs->name, r);
+                               return r;
+                       }
+                       r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+                       /* XXX handle errors */
+                       if (r) {
+                               DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
+                                         adev->ip_blocks[i].funcs->name, r);
+                       }
+                       adev->ip_block_status[i].hw = false;
+                       break;
+               }
+       }
+
        for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
                if (!adev->ip_block_status[i].hw)
                        continue;
@@ -2073,7 +2099,8 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
                if (!adev->ip_block_status[i].valid)
                        continue;
                if (adev->ip_blocks[i].funcs->check_soft_reset)
-                       adev->ip_blocks[i].funcs->check_soft_reset(adev);
+                       adev->ip_block_status[i].hang =
+                               adev->ip_blocks[i].funcs->check_soft_reset(adev);
                if (adev->ip_block_status[i].hang) {
                        DRM_INFO("IP block:%d is hang!\n", i);
                        asic_hang = true;
@@ -2102,12 +2129,20 @@ static int amdgpu_pre_soft_reset(struct amdgpu_device *adev)
 
 static bool amdgpu_need_full_reset(struct amdgpu_device *adev)
 {
-       if (adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang ||
-           adev->ip_block_status[AMD_IP_BLOCK_TYPE_SMC].hang ||
-           adev->ip_block_status[AMD_IP_BLOCK_TYPE_ACP].hang ||
-           adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) {
-               DRM_INFO("Some block need full reset!\n");
-               return true;
+       int i;
+
+       for (i = 0; i < adev->num_ip_blocks; i++) {
+               if (!adev->ip_block_status[i].valid)
+                       continue;
+               if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) ||
+                   (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) ||
+                   (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) ||
+                   (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) {
+                       if (adev->ip_block_status[i].hang) {
+                               DRM_INFO("Some block need full reset!\n");
+                               return true;
+                       }
+               }
        }
        return false;
 }
index fe36caf..14f57d9 100644 (file)
@@ -113,24 +113,26 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
        printk("\n");
 }
 
+
 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
 {
        struct drm_device *dev = adev->ddev;
        struct drm_crtc *crtc;
        struct amdgpu_crtc *amdgpu_crtc;
-       u32 line_time_us, vblank_lines;
+       u32 vblank_in_pixels;
        u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
        if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        amdgpu_crtc = to_amdgpu_crtc(crtc);
                        if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
-                               line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) /
-                                       amdgpu_crtc->hw_mode.clock;
-                               vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end -
+                               vblank_in_pixels =
+                                       amdgpu_crtc->hw_mode.crtc_htotal *
+                                       (amdgpu_crtc->hw_mode.crtc_vblank_end -
                                        amdgpu_crtc->hw_mode.crtc_vdisplay +
-                                       (amdgpu_crtc->v_border * 2);
-                               vblank_time_us = vblank_lines * line_time_us;
+                                       (amdgpu_crtc->v_border * 2));
+
+                               vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
                                break;
                        }
                }
index aa074fa..f3efb1c 100644 (file)
@@ -754,6 +754,10 @@ static const char *amdgpu_vram_names[] = {
 
 int amdgpu_bo_init(struct amdgpu_device *adev)
 {
+       /* reserve PAT memory space to WC for VRAM */
+       arch_io_reserve_memtype_wc(adev->mc.aper_base,
+                                  adev->mc.aper_size);
+
        /* Add an MTRR for the VRAM */
        adev->mc.vram_mtrr = arch_phys_wc_add(adev->mc.aper_base,
                                              adev->mc.aper_size);
@@ -769,6 +773,7 @@ void amdgpu_bo_fini(struct amdgpu_device *adev)
 {
        amdgpu_ttm_fini(adev);
        arch_phys_wc_del(adev->mc.vram_mtrr);
+       arch_io_free_memtype_wc(adev->mc.aper_base, adev->mc.aper_size);
 }
 
 int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
index e1fa873..3cb5e90 100644 (file)
@@ -345,8 +345,8 @@ static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
        ent = debugfs_create_file(name,
                                  S_IFREG | S_IRUGO, root,
                                  ring, &amdgpu_debugfs_ring_fops);
-       if (IS_ERR(ent))
-               return PTR_ERR(ent);
+       if (!ent)
+               return -ENOMEM;
 
        i_size_write(ent->d_inode, ring->ring_size + 12);
        ring->ent = ent;
index 887483b..dcaf691 100644 (file)
@@ -555,10 +555,13 @@ struct amdgpu_ttm_tt {
 int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)
 {
        struct amdgpu_ttm_tt *gtt = (void *)ttm;
-       int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
+       unsigned int flags = 0;
        unsigned pinned = 0;
        int r;
 
+       if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY))
+               flags |= FOLL_WRITE;
+
        if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) {
                /* check that we only use anonymous memory
                   to prevent problems with writeback */
@@ -581,7 +584,7 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)
                list_add(&guptask.list, &gtt->guptasks);
                spin_unlock(&gtt->guptasklock);
 
-               r = get_user_pages(userptr, num_pages, write, 0, p, NULL);
+               r = get_user_pages(userptr, num_pages, flags, p, NULL);
 
                spin_lock(&gtt->guptasklock);
                list_del(&guptask.list);
index f80a083..3c082e1 100644 (file)
@@ -1514,14 +1514,16 @@ static int cz_dpm_set_powergating_state(void *handle,
        return 0;
 }
 
-/* borrowed from KV, need future unify */
 static int cz_dpm_get_temperature(struct amdgpu_device *adev)
 {
        int actual_temp = 0;
-       uint32_t temp = RREG32_SMC(0xC0300E0C);
+       uint32_t val = RREG32_SMC(ixTHM_TCON_CUR_TMP);
+       uint32_t temp = REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP);
 
-       if (temp)
+       if (REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL))
                actual_temp = 1000 * ((temp / 8) - 49);
+       else
+               actual_temp = 1000 * (temp / 8);
 
        return actual_temp;
 }
index 613ebb7..4108c68 100644 (file)
@@ -3188,16 +3188,11 @@ static int dce_v10_0_wait_for_idle(void *handle)
        return 0;
 }
 
-static int dce_v10_0_check_soft_reset(void *handle)
+static bool dce_v10_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (dce_v10_0_is_display_hung(adev))
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = true;
-       else
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = false;
-
-       return 0;
+       return dce_v10_0_is_display_hung(adev);
 }
 
 static int dce_v10_0_soft_reset(void *handle)
@@ -3205,9 +3200,6 @@ static int dce_v10_0_soft_reset(void *handle)
        u32 srbm_soft_reset = 0, tmp;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang)
-               return 0;
-
        if (dce_v10_0_is_display_hung(adev))
                srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
 
index 6c6ff57..ee6a48a 100644 (file)
@@ -4087,14 +4087,21 @@ static int gfx_v8_0_rlc_load_microcode(struct amdgpu_device *adev)
 static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev)
 {
        int r;
+       u32 tmp;
 
        gfx_v8_0_rlc_stop(adev);
 
        /* disable CG */
-       WREG32(mmRLC_CGCG_CGLS_CTRL, 0);
+       tmp = RREG32(mmRLC_CGCG_CGLS_CTRL);
+       tmp &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK |
+                RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
+       WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
        if (adev->asic_type == CHIP_POLARIS11 ||
-           adev->asic_type == CHIP_POLARIS10)
-               WREG32(mmRLC_CGCG_CGLS_CTRL_3D, 0);
+           adev->asic_type == CHIP_POLARIS10) {
+               tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
+               tmp &= ~0x3;
+               WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
+       }
 
        /* disable PG */
        WREG32(mmRLC_PG_CNTL, 0);
@@ -5137,7 +5144,7 @@ static int gfx_v8_0_wait_for_idle(void *handle)
        return -ETIMEDOUT;
 }
 
-static int gfx_v8_0_check_soft_reset(void *handle)
+static bool gfx_v8_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
@@ -5189,16 +5196,14 @@ static int gfx_v8_0_check_soft_reset(void *handle)
                                                SRBM_SOFT_RESET, SOFT_RESET_SEM, 1);
 
        if (grbm_soft_reset || srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = true;
                adev->gfx.grbm_soft_reset = grbm_soft_reset;
                adev->gfx.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = false;
                adev->gfx.grbm_soft_reset = 0;
                adev->gfx.srbm_soft_reset = 0;
+               return false;
        }
-
-       return 0;
 }
 
 static void gfx_v8_0_inactive_hqd(struct amdgpu_device *adev,
@@ -5226,7 +5231,8 @@ static int gfx_v8_0_pre_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang)
+       if ((!adev->gfx.grbm_soft_reset) &&
+           (!adev->gfx.srbm_soft_reset))
                return 0;
 
        grbm_soft_reset = adev->gfx.grbm_soft_reset;
@@ -5264,7 +5270,8 @@ static int gfx_v8_0_soft_reset(void *handle)
        u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
        u32 tmp;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang)
+       if ((!adev->gfx.grbm_soft_reset) &&
+           (!adev->gfx.srbm_soft_reset))
                return 0;
 
        grbm_soft_reset = adev->gfx.grbm_soft_reset;
@@ -5334,7 +5341,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang)
+       if ((!adev->gfx.grbm_soft_reset) &&
+           (!adev->gfx.srbm_soft_reset))
                return 0;
 
        grbm_soft_reset = adev->gfx.grbm_soft_reset;
index 1b319f5..c22ef14 100644 (file)
@@ -1099,7 +1099,7 @@ static int gmc_v8_0_wait_for_idle(void *handle)
 
 }
 
-static int gmc_v8_0_check_soft_reset(void *handle)
+static bool gmc_v8_0_check_soft_reset(void *handle)
 {
        u32 srbm_soft_reset = 0;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1116,20 +1116,19 @@ static int gmc_v8_0_check_soft_reset(void *handle)
                                                        SRBM_SOFT_RESET, SOFT_RESET_MC, 1);
        }
        if (srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = true;
                adev->mc.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = false;
                adev->mc.srbm_soft_reset = 0;
+               return false;
        }
-       return 0;
 }
 
 static int gmc_v8_0_pre_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
+       if (!adev->mc.srbm_soft_reset)
                return 0;
 
        gmc_v8_0_mc_stop(adev, &adev->mc.save);
@@ -1145,7 +1144,7 @@ static int gmc_v8_0_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
+       if (!adev->mc.srbm_soft_reset)
                return 0;
        srbm_soft_reset = adev->mc.srbm_soft_reset;
 
@@ -1175,7 +1174,7 @@ static int gmc_v8_0_post_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang)
+       if (!adev->mc.srbm_soft_reset)
                return 0;
 
        gmc_v8_0_mc_resume(adev, &adev->mc.save);
index f325fd8..a9d1094 100644 (file)
@@ -1268,7 +1268,7 @@ static int sdma_v3_0_wait_for_idle(void *handle)
        return -ETIMEDOUT;
 }
 
-static int sdma_v3_0_check_soft_reset(void *handle)
+static bool sdma_v3_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
@@ -1281,14 +1281,12 @@ static int sdma_v3_0_check_soft_reset(void *handle)
        }
 
        if (srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = true;
                adev->sdma.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = false;
                adev->sdma.srbm_soft_reset = 0;
+               return false;
        }
-
-       return 0;
 }
 
 static int sdma_v3_0_pre_soft_reset(void *handle)
@@ -1296,7 +1294,7 @@ static int sdma_v3_0_pre_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang)
+       if (!adev->sdma.srbm_soft_reset)
                return 0;
 
        srbm_soft_reset = adev->sdma.srbm_soft_reset;
@@ -1315,7 +1313,7 @@ static int sdma_v3_0_post_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang)
+       if (!adev->sdma.srbm_soft_reset)
                return 0;
 
        srbm_soft_reset = adev->sdma.srbm_soft_reset;
@@ -1335,7 +1333,7 @@ static int sdma_v3_0_soft_reset(void *handle)
        u32 srbm_soft_reset = 0;
        u32 tmp;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang)
+       if (!adev->sdma.srbm_soft_reset)
                return 0;
 
        srbm_soft_reset = adev->sdma.srbm_soft_reset;
index 8bd0892..3de7bca 100644 (file)
@@ -3499,6 +3499,12 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
                max_sclk = 75000;
                max_mclk = 80000;
        }
+       /* Limit clocks for some HD8600 parts */
+       if (adev->pdev->device == 0x6660 &&
+           adev->pdev->revision == 0x83) {
+               max_sclk = 75000;
+               max_mclk = 80000;
+       }
 
        if (rps->vce_active) {
                rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk;
index d127d59..b4ea229 100644 (file)
@@ -373,7 +373,7 @@ static int tonga_ih_wait_for_idle(void *handle)
        return -ETIMEDOUT;
 }
 
-static int tonga_ih_check_soft_reset(void *handle)
+static bool tonga_ih_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
@@ -384,21 +384,19 @@ static int tonga_ih_check_soft_reset(void *handle)
                                                SOFT_RESET_IH, 1);
 
        if (srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = true;
                adev->irq.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = false;
                adev->irq.srbm_soft_reset = 0;
+               return false;
        }
-
-       return 0;
 }
 
 static int tonga_ih_pre_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
+       if (!adev->irq.srbm_soft_reset)
                return 0;
 
        return tonga_ih_hw_fini(adev);
@@ -408,7 +406,7 @@ static int tonga_ih_post_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
+       if (!adev->irq.srbm_soft_reset)
                return 0;
 
        return tonga_ih_hw_init(adev);
@@ -419,7 +417,7 @@ static int tonga_ih_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang)
+       if (!adev->irq.srbm_soft_reset)
                return 0;
        srbm_soft_reset = adev->irq.srbm_soft_reset;
 
index e0fd9f2..ab3df6d 100644 (file)
@@ -770,7 +770,7 @@ static int uvd_v6_0_wait_for_idle(void *handle)
 }
 
 #define AMDGPU_UVD_STATUS_BUSY_MASK    0xfd
-static int uvd_v6_0_check_soft_reset(void *handle)
+static bool uvd_v6_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
@@ -782,19 +782,19 @@ static int uvd_v6_0_check_soft_reset(void *handle)
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_UVD, 1);
 
        if (srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = true;
                adev->uvd.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = false;
                adev->uvd.srbm_soft_reset = 0;
+               return false;
        }
-       return 0;
 }
+
 static int uvd_v6_0_pre_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang)
+       if (!adev->uvd.srbm_soft_reset)
                return 0;
 
        uvd_v6_0_stop(adev);
@@ -806,7 +806,7 @@ static int uvd_v6_0_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang)
+       if (!adev->uvd.srbm_soft_reset)
                return 0;
        srbm_soft_reset = adev->uvd.srbm_soft_reset;
 
@@ -836,7 +836,7 @@ static int uvd_v6_0_post_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang)
+       if (!adev->uvd.srbm_soft_reset)
                return 0;
 
        mdelay(5);
index 3f6db4e..8533269 100644 (file)
@@ -561,7 +561,7 @@ static int vce_v3_0_wait_for_idle(void *handle)
 #define  AMDGPU_VCE_STATUS_BUSY_MASK (VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK | \
                                      VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK)
 
-static int vce_v3_0_check_soft_reset(void *handle)
+static bool vce_v3_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset = 0;
@@ -591,16 +591,15 @@ static int vce_v3_0_check_soft_reset(void *handle)
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
        }
        WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+       mutex_unlock(&adev->grbm_idx_mutex);
 
        if (srbm_soft_reset) {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = true;
                adev->vce.srbm_soft_reset = srbm_soft_reset;
+               return true;
        } else {
-               adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = false;
                adev->vce.srbm_soft_reset = 0;
+               return false;
        }
-       mutex_unlock(&adev->grbm_idx_mutex);
-       return 0;
 }
 
 static int vce_v3_0_soft_reset(void *handle)
@@ -608,7 +607,7 @@ static int vce_v3_0_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 srbm_soft_reset;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+       if (!adev->vce.srbm_soft_reset)
                return 0;
        srbm_soft_reset = adev->vce.srbm_soft_reset;
 
@@ -638,7 +637,7 @@ static int vce_v3_0_pre_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+       if (!adev->vce.srbm_soft_reset)
                return 0;
 
        mdelay(5);
@@ -651,7 +650,7 @@ static int vce_v3_0_post_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
+       if (!adev->vce.srbm_soft_reset)
                return 0;
 
        mdelay(5);
index c934b78..bec8125 100644 (file)
@@ -165,7 +165,7 @@ struct amd_ip_funcs {
        /* poll for idle */
        int (*wait_for_idle)(void *handle);
        /* check soft reset the IP block */
-       int (*check_soft_reset)(void *handle);
+       bool (*check_soft_reset)(void *handle);
        /* pre soft reset the IP block */
        int (*pre_soft_reset)(void *handle);
        /* soft reset the IP block */
index 92b1178..8cee4e0 100644 (file)
@@ -49,6 +49,7 @@ static const pem_event_action * const uninitialize_event[] = {
        uninitialize_display_phy_access_tasks,
        disable_gfx_voltage_island_power_gating_tasks,
        disable_gfx_clock_gating_tasks,
+       uninitialize_thermal_controller_tasks,
        set_boot_state_tasks,
        adjust_power_state_tasks,
        disable_dynamic_state_management_tasks,
index 7e4fcbb..9604249 100644 (file)
@@ -1785,6 +1785,21 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c
        return 0;
 }
 
+static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr)
+{
+       int actual_temp = 0;
+       uint32_t val = cgs_read_ind_register(hwmgr->device,
+                                            CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP);
+       uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP);
+
+       if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL))
+               actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+       else
+               actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+       return actual_temp;
+}
+
 static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
 {
        struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
@@ -1881,6 +1896,9 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)
        case AMDGPU_PP_SENSOR_VCE_POWER:
                *value = cz_hwmgr->vce_power_gated ? 0 : 1;
                return 0;
+       case AMDGPU_PP_SENSOR_GPU_TEMP:
+               *value = cz_thermal_get_temperature(hwmgr);
+               return 0;
        default:
                return -EINVAL;
        }
index 508245d..609996c 100644 (file)
@@ -1030,20 +1030,19 @@ static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
        /* disable SCLK dpm */
-       if (!data->sclk_dpm_key_disabled)
-               PP_ASSERT_WITH_CODE(
-                               (smum_send_msg_to_smc(hwmgr->smumgr,
-                                               PPSMC_MSG_DPM_Disable) == 0),
-                               "Failed to disable SCLK DPM!",
-                               return -EINVAL);
+       if (!data->sclk_dpm_key_disabled) {
+               PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
+                               "Trying to disable SCLK DPM when DPM is disabled",
+                               return 0);
+               smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Disable);
+       }
 
        /* disable MCLK dpm */
        if (!data->mclk_dpm_key_disabled) {
-               PP_ASSERT_WITH_CODE(
-                               (smum_send_msg_to_smc(hwmgr->smumgr,
-                                               PPSMC_MSG_MCLKDPM_Disable) == 0),
-                               "Failed to disable MCLK DPM!",
-                               return -EINVAL);
+               PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
+                               "Trying to disable MCLK DPM when DPM is disabled",
+                               return 0);
+               smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_Disable);
        }
 
        return 0;
@@ -1069,10 +1068,13 @@ static int smu7_stop_dpm(struct pp_hwmgr *hwmgr)
                                return -EINVAL);
        }
 
-       if (smu7_disable_sclk_mclk_dpm(hwmgr)) {
-               printk(KERN_ERR "Failed to disable Sclk DPM and Mclk DPM!");
-               return -EINVAL;
-       }
+       smu7_disable_sclk_mclk_dpm(hwmgr);
+
+       PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr),
+                       "Trying to disable voltage DPM when DPM is disabled",
+                       return 0);
+
+       smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Disable);
 
        return 0;
 }
@@ -1226,7 +1228,7 @@ int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
        PP_ASSERT_WITH_CODE((0 == tmp_result),
                        "Failed to enable VR hot GPIO interrupt!", result = tmp_result);
 
-       smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay);
+       smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_NoDisplay);
 
        tmp_result = smu7_enable_sclk_control(hwmgr);
        PP_ASSERT_WITH_CODE((0 == tmp_result),
@@ -1306,6 +1308,12 @@ int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
        PP_ASSERT_WITH_CODE((tmp_result == 0),
                        "Failed to disable thermal auto throttle!", result = tmp_result);
 
+       if (1 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) {
+               PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableAvfs)),
+                                       "Failed to disable AVFS!",
+                                       return -EINVAL);
+       }
+
        tmp_result = smu7_stop_dpm(hwmgr);
        PP_ASSERT_WITH_CODE((tmp_result == 0),
                        "Failed to stop DPM!", result = tmp_result);
@@ -1452,8 +1460,10 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
        struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL;
 
 
-       if (table_info != NULL)
-               sclk_table = table_info->vdd_dep_on_sclk;
+       if (table_info == NULL)
+               return -EINVAL;
+
+       sclk_table = table_info->vdd_dep_on_sclk;
 
        for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {
                vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
@@ -3802,13 +3812,15 @@ static inline bool smu7_are_power_levels_equal(const struct smu7_performance_lev
 
 int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
 {
-       const struct smu7_power_state *psa = cast_const_phw_smu7_power_state(pstate1);
-       const struct smu7_power_state *psb = cast_const_phw_smu7_power_state(pstate2);
+       const struct smu7_power_state *psa;
+       const struct smu7_power_state *psb;
        int i;
 
        if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
                return -EINVAL;
 
+       psa = cast_const_phw_smu7_power_state(pstate1);
+       psb = cast_const_phw_smu7_power_state(pstate2);
        /* If the two states don't even have the same number of performance levels they cannot be the same state. */
        if (psa->performance_level_count != psb->performance_level_count) {
                *equal = false;
@@ -4324,6 +4336,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
        .set_mclk_od = smu7_set_mclk_od,
        .get_clock_by_type = smu7_get_clock_by_type,
        .read_sensor = smu7_read_sensor,
+       .dynamic_state_management_disable = smu7_disable_dpm_tasks,
 };
 
 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
index eda802b..8c889ca 100644 (file)
@@ -2458,7 +2458,7 @@ static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr,
                        PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),
                                "Invalid VramInfo table.", return -EINVAL);
 
-                       if (!data->is_memory_gddr5) {
+                       if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) {
                                table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;
                                table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;
                                for (k = 0; k < table->num_entries; k++) {
index 2f58e9e..a51f8cb 100644 (file)
@@ -332,17 +332,19 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
 {
        struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 
-       if (dcrtc->dpms != dpms) {
-               dcrtc->dpms = dpms;
-               if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms))
-                       WARN_ON(clk_prepare_enable(dcrtc->clk));
-               armada_drm_crtc_update(dcrtc);
-               if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms))
-                       clk_disable_unprepare(dcrtc->clk);
+       if (dpms_blanked(dcrtc->dpms) != dpms_blanked(dpms)) {
                if (dpms_blanked(dpms))
                        armada_drm_vblank_off(dcrtc);
-               else
+               else if (!IS_ERR(dcrtc->clk))
+                       WARN_ON(clk_prepare_enable(dcrtc->clk));
+               dcrtc->dpms = dpms;
+               armada_drm_crtc_update(dcrtc);
+               if (!dpms_blanked(dpms))
                        drm_crtc_vblank_on(&dcrtc->crtc);
+               else if (!IS_ERR(dcrtc->clk))
+                       clk_disable_unprepare(dcrtc->clk);
+       } else if (dcrtc->dpms != dpms) {
+               dcrtc->dpms = dpms;
        }
 }
 
index 608df4c..0743e65 100644 (file)
@@ -267,6 +267,8 @@ int ast_mm_init(struct ast_private *ast)
                return ret;
        }
 
+       arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
+                                  pci_resource_len(dev->pdev, 0));
        ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
                                        pci_resource_len(dev->pdev, 0));
 
@@ -275,11 +277,15 @@ int ast_mm_init(struct ast_private *ast)
 
 void ast_mm_fini(struct ast_private *ast)
 {
+       struct drm_device *dev = ast->dev;
+
        ttm_bo_device_release(&ast->ttm.bdev);
 
        ast_ttm_global_release(ast);
 
        arch_phys_wc_del(ast->fb_mtrr);
+       arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
+                               pci_resource_len(dev->pdev, 0));
 }
 
 void ast_ttm_placement(struct ast_bo *bo, int domain)
index bb2438d..5e7e63c 100644 (file)
@@ -267,6 +267,9 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
                return ret;
        }
 
+       arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
+                                  pci_resource_len(dev->pdev, 0));
+
        cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
                                           pci_resource_len(dev->pdev, 0));
 
@@ -276,6 +279,8 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
 
 void cirrus_mm_fini(struct cirrus_device *cirrus)
 {
+       struct drm_device *dev = cirrus->dev;
+
        if (!cirrus->mm_inited)
                return;
 
@@ -285,6 +290,8 @@ void cirrus_mm_fini(struct cirrus_device *cirrus)
 
        arch_phys_wc_del(cirrus->fb_mtrr);
        cirrus->fb_mtrr = 0;
+       arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
+                               pci_resource_len(dev->pdev, 0));
 }
 
 void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
index 1df2d33..ffb2ab3 100644 (file)
@@ -54,9 +54,6 @@ int drm_name_info(struct seq_file *m, void *data)
 
        mutex_lock(&dev->master_mutex);
        master = dev->master;
-       if (!master)
-               goto out_unlock;
-
        seq_printf(m, "%s", dev->driver->name);
        if (dev->dev)
                seq_printf(m, " dev=%s", dev_name(dev->dev));
@@ -65,7 +62,6 @@ int drm_name_info(struct seq_file *m, void *data)
        if (dev->unique)
                seq_printf(m, " unique=%s", dev->unique);
        seq_printf(m, "\n");
-out_unlock:
        mutex_unlock(&dev->master_mutex);
 
        return 0;
index cb86c7e..d923013 100644 (file)
@@ -329,20 +329,34 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
        /*
         * Append a LINK to the submitted command buffer to return to
         * the ring buffer.  return_target is the ring target address.
-        * We need three dwords: event, wait, link.
+        * We need at most 7 dwords in the return target: 2 cache flush +
+        * 2 semaphore stall + 1 event + 1 wait + 1 link.
         */
-       return_dwords = 3;
+       return_dwords = 7;
        return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);
        CMD_LINK(cmdbuf, return_dwords, return_target);
 
        /*
-        * Append event, wait and link pointing back to the wait
-        * command to the ring buffer.
+        * Append a cache flush, stall, event, wait and link pointing back to
+        * the wait command to the ring buffer.
         */
+       if (gpu->exec_state == ETNA_PIPE_2D) {
+               CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
+                                      VIVS_GL_FLUSH_CACHE_PE2D);
+       } else {
+               CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
+                                      VIVS_GL_FLUSH_CACHE_DEPTH |
+                                      VIVS_GL_FLUSH_CACHE_COLOR);
+               CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
+                                      VIVS_TS_FLUSH_CACHE_FLUSH);
+       }
+       CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+       CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
        CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
                       VIVS_GL_EVENT_FROM_PE);
        CMD_WAIT(buffer);
-       CMD_LINK(buffer, 2, return_target + 8);
+       CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) +
+                           buffer->user_size - 4);
 
        if (drm_debug & DRM_UT_DRIVER)
                pr_info("stream link to 0x%08x @ 0x%08x %p\n",
index 5ce3603..0370b84 100644 (file)
@@ -748,19 +748,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages(
        int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
        struct page **pvec;
        uintptr_t ptr;
+       unsigned int flags = 0;
 
        pvec = drm_malloc_ab(npages, sizeof(struct page *));
        if (!pvec)
                return ERR_PTR(-ENOMEM);
 
+       if (!etnaviv_obj->userptr.ro)
+               flags |= FOLL_WRITE;
+
        pinned = 0;
        ptr = etnaviv_obj->userptr.ptr;
 
        down_read(&mm->mmap_sem);
        while (pinned < npages) {
                ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
-                                           !etnaviv_obj->userptr.ro, 0,
-                                           pvec + pinned, NULL);
+                                           flags, pvec + pinned, NULL);
                if (ret < 0)
                        break;
 
index d3796ed..169ac96 100644 (file)
@@ -330,7 +330,8 @@ u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu,
                        return (u32)buf->vram_node.start;
 
                mutex_lock(&mmu->lock);
-               ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, buf->size);
+               ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node,
+                                             buf->size + SZ_64K);
                if (ret < 0) {
                        mutex_unlock(&mmu->lock);
                        return 0;
index aa92dec..fbd13fa 100644 (file)
@@ -488,7 +488,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
                goto err_free;
        }
 
-       ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec);
+       ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE,
+               g2d_userptr->vec);
        if (ret != npages) {
                DRM_ERROR("failed to get user pages from userptr.\n");
                if (ret < 0)
index 3371635..b2d5e18 100644 (file)
@@ -51,6 +51,7 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
                           DCU_MODE_DCU_MODE(DCU_MODE_OFF));
        regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
                     DCU_UPDATE_MODE_READREG);
+       clk_disable_unprepare(fsl_dev->pix_clk);
 }
 
 static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
@@ -58,6 +59,7 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 
+       clk_prepare_enable(fsl_dev->pix_clk);
        regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
                           DCU_MODE_DCU_MODE_MASK,
                           DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
@@ -116,8 +118,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
                     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
                     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
                     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
-       regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
-                    DCU_UPDATE_MODE_READREG);
        return;
 }
 
index 0884c45..e04efbe 100644 (file)
@@ -267,12 +267,8 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
                return ret;
        }
 
-       ret = clk_prepare_enable(fsl_dev->pix_clk);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable pix clk\n");
-               goto disable_dcu_clk;
-       }
-
+       if (fsl_dev->tcon)
+               fsl_tcon_bypass_enable(fsl_dev->tcon);
        fsl_dcu_drm_init_planes(fsl_dev->drm);
        drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state);
 
@@ -284,10 +280,6 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)
        enable_irq(fsl_dev->irq);
 
        return 0;
-
-disable_dcu_clk:
-       clk_disable_unprepare(fsl_dev->clk);
-       return ret;
 }
 #endif
 
@@ -401,18 +393,12 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
                goto disable_clk;
        }
 
-       ret = clk_prepare_enable(fsl_dev->pix_clk);
-       if (ret < 0) {
-               dev_err(dev, "failed to enable pix clk\n");
-               goto unregister_pix_clk;
-       }
-
        fsl_dev->tcon = fsl_tcon_init(dev);
 
        drm = drm_dev_alloc(driver, dev);
        if (IS_ERR(drm)) {
                ret = PTR_ERR(drm);
-               goto disable_pix_clk;
+               goto unregister_pix_clk;
        }
 
        fsl_dev->dev = dev;
@@ -433,8 +419,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
 
 unref:
        drm_dev_unref(drm);
-disable_pix_clk:
-       clk_disable_unprepare(fsl_dev->pix_clk);
 unregister_pix_clk:
        clk_unregister(fsl_dev->pix_clk);
 disable_clk:
@@ -447,7 +431,6 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev)
        struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
 
        clk_disable_unprepare(fsl_dev->clk);
-       clk_disable_unprepare(fsl_dev->pix_clk);
        clk_unregister(fsl_dev->pix_clk);
        drm_put_dev(fsl_dev->drm);
 
index a7e5486..9e6f7d8 100644 (file)
@@ -211,11 +211,6 @@ void fsl_dcu_drm_init_planes(struct drm_device *dev)
                for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
                        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
        }
-       regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
-                          DCU_MODE_DCU_MODE_MASK,
-                          DCU_MODE_DCU_MODE(DCU_MODE_OFF));
-       regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
-                    DCU_UPDATE_MODE_READREG);
 }
 
 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
index 26edcc8..e1dd75b 100644 (file)
 #include "fsl_dcu_drm_drv.h"
 #include "fsl_tcon.h"
 
-static int
-fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
-                                struct drm_crtc_state *crtc_state,
-                                struct drm_connector_state *conn_state)
-{
-       return 0;
-}
-
-static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-
-       if (fsl_dev->tcon)
-               fsl_tcon_bypass_disable(fsl_dev->tcon);
-}
-
-static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-
-       if (fsl_dev->tcon)
-               fsl_tcon_bypass_enable(fsl_dev->tcon);
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-       .atomic_check = fsl_dcu_drm_encoder_atomic_check,
-       .disable = fsl_dcu_drm_encoder_disable,
-       .enable = fsl_dcu_drm_encoder_enable,
-};
-
 static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
 {
        drm_encoder_cleanup(encoder);
@@ -68,13 +36,16 @@ int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
        int ret;
 
        encoder->possible_crtcs = 1;
+
+       /* Use bypass mode for parallel RGB/LVDS encoder */
+       if (fsl_dev->tcon)
+               fsl_tcon_bypass_enable(fsl_dev->tcon);
+
        ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs,
                               DRM_MODE_ENCODER_LVDS, NULL);
        if (ret < 0)
                return ret;
 
-       drm_encoder_helper_add(encoder, &encoder_helper_funcs);
-
        return 0;
 }
 
index e537930..c6f780f 100644 (file)
@@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
        pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
        if (pvec != NULL) {
                struct mm_struct *mm = obj->userptr.mm->mm;
+               unsigned int flags = 0;
+
+               if (!obj->userptr.read_only)
+                       flags |= FOLL_WRITE;
 
                ret = -EFAULT;
                if (atomic_inc_not_zero(&mm->mm_users)) {
@@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
                                        (work->task, mm,
                                         obj->userptr.ptr + pinned * PAGE_SIZE,
                                         npages - pinned,
-                                        !obj->userptr.read_only, 0,
+                                        flags,
                                         pvec + pinned, NULL);
                                if (ret < 0)
                                        break;
index 919b35f..dcf7d11 100644 (file)
@@ -266,6 +266,9 @@ int mgag200_mm_init(struct mga_device *mdev)
                return ret;
        }
 
+       arch_io_reserve_memtype_wc(pci_resource_start(dev->pdev, 0),
+                                  pci_resource_len(dev->pdev, 0));
+
        mdev->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
                                         pci_resource_len(dev->pdev, 0));
 
@@ -274,10 +277,14 @@ int mgag200_mm_init(struct mga_device *mdev)
 
 void mgag200_mm_fini(struct mga_device *mdev)
 {
+       struct drm_device *dev = mdev->dev;
+
        ttm_bo_device_release(&mdev->ttm.bdev);
 
        mgag200_ttm_global_release(mdev);
 
+       arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
+                               pci_resource_len(dev->pdev, 0));
        arch_phys_wc_del(mdev->fb_mtrr);
        mdev->fb_mtrr = 0;
 }
index 1825dbc..a6dbe82 100644 (file)
@@ -398,6 +398,9 @@ nouveau_ttm_init(struct nouveau_drm *drm)
        /* VRAM init */
        drm->gem.vram_available = drm->device.info.ram_user;
 
+       arch_io_reserve_memtype_wc(device->func->resource_addr(device, 1),
+                                  device->func->resource_size(device, 1));
+
        ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM,
                              drm->gem.vram_available >> PAGE_SHIFT);
        if (ret) {
@@ -430,6 +433,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)
 void
 nouveau_ttm_fini(struct nouveau_drm *drm)
 {
+       struct nvkm_device *device = nvxx_device(&drm->device);
+
        ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM);
        ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT);
 
@@ -439,4 +444,7 @@ nouveau_ttm_fini(struct nouveau_drm *drm)
 
        arch_phys_wc_del(drm->ttm.mtrr);
        drm->ttm.mtrr = 0;
+       arch_io_free_memtype_wc(device->func->resource_addr(device, 1),
+                               device->func->resource_size(device, 1));
+
 }
index 6a4b020..5a26eb4 100644 (file)
@@ -156,19 +156,20 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
        struct drm_device *dev = rdev->ddev;
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;
-       u32 line_time_us, vblank_lines;
+       u32 vblank_in_pixels;
        u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
        if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        radeon_crtc = to_radeon_crtc(crtc);
                        if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                               line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
-                                       radeon_crtc->hw_mode.clock;
-                               vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
-                                       radeon_crtc->hw_mode.crtc_vdisplay +
-                                       (radeon_crtc->v_border * 2);
-                               vblank_time_us = vblank_lines * line_time_us;
+                               vblank_in_pixels =
+                                       radeon_crtc->hw_mode.crtc_htotal *
+                                       (radeon_crtc->hw_mode.crtc_vblank_end -
+                                        radeon_crtc->hw_mode.crtc_vdisplay +
+                                        (radeon_crtc->v_border * 2));
+
+                               vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock;
                                break;
                        }
                }
index 50e96d2..e18839d 100644 (file)
@@ -927,6 +927,16 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
        return ret;
 }
 
+static void radeon_connector_unregister(struct drm_connector *connector)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+
+       if (radeon_connector->ddc_bus->has_aux) {
+               drm_dp_aux_unregister(&radeon_connector->ddc_bus->aux);
+               radeon_connector->ddc_bus->has_aux = false;
+       }
+}
+
 static void radeon_connector_destroy(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -984,6 +994,7 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = radeon_lvds_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .set_property = radeon_lvds_set_property,
 };
@@ -1111,6 +1122,7 @@ static const struct drm_connector_funcs radeon_vga_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = radeon_vga_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .set_property = radeon_connector_set_property,
 };
@@ -1188,6 +1200,7 @@ static const struct drm_connector_funcs radeon_tv_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
        .detect = radeon_tv_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .set_property = radeon_connector_set_property,
 };
@@ -1519,6 +1532,7 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = {
        .detect = radeon_dvi_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = radeon_connector_set_property,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .force = radeon_dvi_force,
 };
@@ -1832,6 +1846,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = {
        .detect = radeon_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = radeon_connector_set_property,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .force = radeon_dvi_force,
 };
@@ -1841,6 +1856,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = {
        .detect = radeon_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = radeon_lvds_set_property,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .force = radeon_dvi_force,
 };
@@ -1850,6 +1866,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
        .detect = radeon_dp_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = radeon_lvds_set_property,
+       .early_unregister = radeon_connector_unregister,
        .destroy = radeon_connector_destroy,
        .force = radeon_dvi_force,
 };
index b8ab30a..cdb8cb5 100644 (file)
@@ -1675,20 +1675,20 @@ int radeon_modeset_init(struct radeon_device *rdev)
 
 void radeon_modeset_fini(struct radeon_device *rdev)
 {
-       radeon_fbdev_fini(rdev);
-       kfree(rdev->mode_info.bios_hardcoded_edid);
-
-       /* free i2c buses */
-       radeon_i2c_fini(rdev);
-
        if (rdev->mode_info.mode_config_initialized) {
-               radeon_afmt_fini(rdev);
                drm_kms_helper_poll_fini(rdev->ddev);
                radeon_hpd_fini(rdev);
                drm_crtc_force_disable_all(rdev->ddev);
+               radeon_fbdev_fini(rdev);
+               radeon_afmt_fini(rdev);
                drm_mode_config_cleanup(rdev->ddev);
                rdev->mode_info.mode_config_initialized = false;
        }
+
+       kfree(rdev->mode_info.bios_hardcoded_edid);
+
+       /* free i2c buses */
+       radeon_i2c_fini(rdev);
 }
 
 static bool is_hdtv_mode(const struct drm_display_mode *mode)
index 91c8f43..00ea000 100644 (file)
  *   2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI
  *   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
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       47
+#define KMS_DRIVER_MINOR       48
 #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);
index 021aa00..29f7817 100644 (file)
@@ -982,9 +982,8 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 {
        if (!i2c)
                return;
+       WARN_ON(i2c->has_aux);
        i2c_del_adapter(&i2c->adapter);
-       if (i2c->has_aux)
-               drm_dp_aux_unregister(&i2c->aux);
        kfree(i2c);
 }
 
index be30861..41b72ce 100644 (file)
@@ -446,6 +446,10 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
 
 int radeon_bo_init(struct radeon_device *rdev)
 {
+       /* reserve PAT memory space to WC for VRAM */
+       arch_io_reserve_memtype_wc(rdev->mc.aper_base,
+                                  rdev->mc.aper_size);
+
        /* Add an MTRR for the VRAM */
        if (!rdev->fastfb_working) {
                rdev->mc.vram_mtrr = arch_phys_wc_add(rdev->mc.aper_base,
@@ -463,6 +467,7 @@ void radeon_bo_fini(struct radeon_device *rdev)
 {
        radeon_ttm_fini(rdev);
        arch_phys_wc_del(rdev->mc.vram_mtrr);
+       arch_io_free_memtype_wc(rdev->mc.aper_base, rdev->mc.aper_size);
 }
 
 /* Returns how many bytes TTM can move per IB.
index 4552682..3de5e6e 100644 (file)
@@ -566,7 +566,8 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm)
                uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE;
                struct page **pages = ttm->pages + pinned;
 
-               r = get_user_pages(userptr, num_pages, write, 0, pages, NULL);
+               r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0,
+                                  pages, NULL);
                if (r < 0)
                        goto release_pages;
 
index 7ee9aaf..e402be8 100644 (file)
@@ -4431,6 +4431,7 @@ static bool si_vm_reg_valid(u32 reg)
        case SPI_CONFIG_CNTL:
        case SPI_CONFIG_CNTL_1:
        case TA_CNTL_AUX:
+       case TA_CS_BC_BASE_ADDR:
                return true;
        default:
                DRM_ERROR("Invalid register 0x%x in CS\n", reg);
index eb220ee..65a911d 100644 (file)
 #define        SPI_LB_CU_MASK                                  0x9354
 
 #define        TA_CNTL_AUX                                     0x9508
+#define        TA_CS_BC_BASE_ADDR                              0x950C
 
 #define CC_RB_BACKEND_DISABLE                          0x98F4
 #define                BACKEND_DISABLE(x)                      ((x) << 16)
index 7e2a12c..1a3ad76 100644 (file)
@@ -241,8 +241,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
        down_read(&current->mm->mmap_sem);
        ret = get_user_pages((unsigned long)xfer->mem_addr,
                             vsg->num_pages,
-                            (vsg->direction == DMA_FROM_DEVICE),
-                            0, vsg->pages, NULL);
+                            (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0,
+                            vsg->pages, NULL);
 
        up_read(&current->mm->mmap_sem);
        if (ret != vsg->num_pages) {
index e8ae3dc..18061a4 100644 (file)
@@ -241,15 +241,15 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
                              void *ptr);
 
 MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
-module_param_named(enable_fbdev, enable_fbdev, int, 0600);
+module_param_named(enable_fbdev, enable_fbdev, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages");
-module_param_named(force_dma_api, vmw_force_iommu, int, 0600);
+module_param_named(force_dma_api, vmw_force_iommu, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
-module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
+module_param_named(restrict_iommu, vmw_restrict_iommu, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
-module_param_named(force_coherent, vmw_force_coherent, int, 0600);
+module_param_named(force_coherent, vmw_force_coherent, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
-module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
+module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
 module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
 
index 070d750..1e59a48 100644 (file)
@@ -43,7 +43,7 @@
 
 #define VMWGFX_DRIVER_DATE "20160210"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 10
+#define VMWGFX_DRIVER_MINOR 11
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
index dc5beff..c7b53d9 100644 (file)
 
 #define VMW_RES_HT_ORDER 12
 
+/**
+ * enum vmw_resource_relocation_type - Relocation type for resources
+ *
+ * @vmw_res_rel_normal: Traditional relocation. The resource id in the
+ * command stream is replaced with the actual id after validation.
+ * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced
+ * with a NOP.
+ * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id
+ * after validation is -1, the command is replaced with a NOP. Otherwise no
+ * action.
+ */
+enum vmw_resource_relocation_type {
+       vmw_res_rel_normal,
+       vmw_res_rel_nop,
+       vmw_res_rel_cond_nop,
+       vmw_res_rel_max
+};
+
 /**
  * struct vmw_resource_relocation - Relocation info for resources
  *
  * @head: List head for the software context's relocation list.
  * @res: Non-ref-counted pointer to the resource.
- * @offset: Offset of 4 byte entries into the command buffer where the
+ * @offset: Offset of single byte entries into the command buffer where the
  * id that needs fixup is located.
+ * @rel_type: Type of relocation.
  */
 struct vmw_resource_relocation {
        struct list_head head;
        const struct vmw_resource *res;
-       unsigned long offset;
+       u32 offset:29;
+       enum vmw_resource_relocation_type rel_type:3;
 };
 
 /**
@@ -109,7 +129,18 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
                                   struct vmw_dma_buffer *vbo,
                                   bool validate_as_mob,
                                   uint32_t *p_val_node);
-
+/**
+ * vmw_ptr_diff - Compute the offset from a to b in bytes
+ *
+ * @a: A starting pointer.
+ * @b: A pointer offset in the same address space.
+ *
+ * Returns: The offset in bytes between the two pointers.
+ */
+static size_t vmw_ptr_diff(void *a, void *b)
+{
+       return (unsigned long) b - (unsigned long) a;
+}
 
 /**
  * vmw_resources_unreserve - unreserve resources previously reserved for
@@ -409,11 +440,14 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
  * @list: Pointer to head of relocation list.
  * @res: The resource.
  * @offset: Offset into the command buffer currently being parsed where the
- * id that needs fixup is located. Granularity is 4 bytes.
+ * id that needs fixup is located. Granularity is one byte.
+ * @rel_type: Relocation type.
  */
 static int vmw_resource_relocation_add(struct list_head *list,
                                       const struct vmw_resource *res,
-                                      unsigned long offset)
+                                      unsigned long offset,
+                                      enum vmw_resource_relocation_type
+                                      rel_type)
 {
        struct vmw_resource_relocation *rel;
 
@@ -425,6 +459,7 @@ static int vmw_resource_relocation_add(struct list_head *list,
 
        rel->res = res;
        rel->offset = offset;
+       rel->rel_type = rel_type;
        list_add_tail(&rel->head, list);
 
        return 0;
@@ -459,11 +494,24 @@ static void vmw_resource_relocations_apply(uint32_t *cb,
 {
        struct vmw_resource_relocation *rel;
 
+       /* Validate the struct vmw_resource_relocation member size */
+       BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29));
+       BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3));
+
        list_for_each_entry(rel, list, head) {
-               if (likely(rel->res != NULL))
-                       cb[rel->offset] = rel->res->id;
-               else
-                       cb[rel->offset] = SVGA_3D_CMD_NOP;
+               u32 *addr = (u32 *)((unsigned long) cb + rel->offset);
+               switch (rel->rel_type) {
+               case vmw_res_rel_normal:
+                       *addr = rel->res->id;
+                       break;
+               case vmw_res_rel_nop:
+                       *addr = SVGA_3D_CMD_NOP;
+                       break;
+               default:
+                       if (rel->res->id == -1)
+                               *addr = SVGA_3D_CMD_NOP;
+                       break;
+               }
        }
 }
 
@@ -655,7 +703,9 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
        *p_val = NULL;
        ret = vmw_resource_relocation_add(&sw_context->res_relocations,
                                          res,
-                                         id_loc - sw_context->buf_start);
+                                         vmw_ptr_diff(sw_context->buf_start,
+                                                      id_loc),
+                                         vmw_res_rel_normal);
        if (unlikely(ret != 0))
                return ret;
 
@@ -721,7 +771,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
 
                return vmw_resource_relocation_add
                        (&sw_context->res_relocations, res,
-                        id_loc - sw_context->buf_start);
+                        vmw_ptr_diff(sw_context->buf_start, id_loc),
+                        vmw_res_rel_normal);
        }
 
        ret = vmw_user_resource_lookup_handle(dev_priv,
@@ -2143,10 +2194,10 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
                return ret;
 
        return vmw_resource_relocation_add(&sw_context->res_relocations,
-                                          NULL, &cmd->header.id -
-                                          sw_context->buf_start);
-
-       return 0;
+                                          NULL,
+                                          vmw_ptr_diff(sw_context->buf_start,
+                                                       &cmd->header.id),
+                                          vmw_res_rel_nop);
 }
 
 /**
@@ -2188,10 +2239,10 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
                return ret;
 
        return vmw_resource_relocation_add(&sw_context->res_relocations,
-                                          NULL, &cmd->header.id -
-                                          sw_context->buf_start);
-
-       return 0;
+                                          NULL,
+                                          vmw_ptr_diff(sw_context->buf_start,
+                                                       &cmd->header.id),
+                                          vmw_res_rel_nop);
 }
 
 /**
@@ -2848,8 +2899,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv,
  * @header: Pointer to the command header in the command stream.
  *
  * Check that the view exists, and if it was not created using this
- * command batch, make sure it's validated (present in the device) so that
- * the remove command will not confuse the device.
+ * command batch, conditionally make this command a NOP.
  */
 static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,
                                  struct vmw_sw_context *sw_context,
@@ -2877,10 +2927,16 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,
                return ret;
 
        /*
-        * Add view to the validate list iff it was not created using this
-        * command batch.
+        * If the view wasn't created during this command batch, it might
+        * have been removed due to a context swapout, so add a
+        * relocation to conditionally make this command a NOP to avoid
+        * device errors.
         */
-       return vmw_view_res_val_add(sw_context, view);
+       return vmw_resource_relocation_add(&sw_context->res_relocations,
+                                          view,
+                                          vmw_ptr_diff(sw_context->buf_start,
+                                                       &cmd->header.id),
+                                          vmw_res_rel_cond_nop);
 }
 
 /**
@@ -3029,6 +3085,35 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,
                                   cmd->body.shaderResourceViewId);
 }
 
+/**
+ * vmw_cmd_dx_transfer_from_buffer -
+ * Validate an SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command
+ *
+ * @dev_priv: Pointer to a device private struct.
+ * @sw_context: The software context being used for this batch.
+ * @header: Pointer to the command header in the command stream.
+ */
+static int vmw_cmd_dx_transfer_from_buffer(struct vmw_private *dev_priv,
+                                          struct vmw_sw_context *sw_context,
+                                          SVGA3dCmdHeader *header)
+{
+       struct {
+               SVGA3dCmdHeader header;
+               SVGA3dCmdDXTransferFromBuffer body;
+       } *cmd = container_of(header, typeof(*cmd), header);
+       int ret;
+
+       ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                               user_surface_converter,
+                               &cmd->body.srcSid, NULL);
+       if (ret != 0)
+               return ret;
+
+       return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
+                                user_surface_converter,
+                                &cmd->body.destSid, NULL);
+}
+
 static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
                                struct vmw_sw_context *sw_context,
                                void *buf, uint32_t *size)
@@ -3379,6 +3464,9 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
                    &vmw_cmd_buffer_copy_check, true, false, true),
        VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION,
                    &vmw_cmd_pred_copy_check, true, false, true),
+       VMW_CMD_DEF(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER,
+                   &vmw_cmd_dx_transfer_from_buffer,
+                   true, false, true),
 };
 
 static int vmw_cmd_check(struct vmw_private *dev_priv,
@@ -3848,14 +3936,14 @@ static void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv,
        int ret;
 
        *header = NULL;
-       if (!dev_priv->cman || kernel_commands)
-               return kernel_commands;
-
        if (command_size > SVGA_CB_MAX_SIZE) {
                DRM_ERROR("Command buffer is too large.\n");
                return ERR_PTR(-EINVAL);
        }
 
+       if (!dev_priv->cman || kernel_commands)
+               return kernel_commands;
+
        /* If possible, add a little space for fencing. */
        cmdbuf_size = command_size + 512;
        cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE);
@@ -4232,9 +4320,6 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
        ttm_bo_unref(&query_val.bo);
        ttm_bo_unref(&pinned_val.bo);
        vmw_dmabuf_unreference(&dev_priv->pinned_bo);
-       DRM_INFO("Dummy query bo pin count: %d\n",
-                dev_priv->dummy_query_bo->pin_count);
-
 out_unlock:
        return;
 
index 6a328d5..52ca1c9 100644 (file)
@@ -574,10 +574,8 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
                bool nonblock = !!(flags & drm_vmw_synccpu_dontblock);
                long lret;
 
-               if (nonblock)
-                       return reservation_object_test_signaled_rcu(bo->resv, true) ? 0 : -EBUSY;
-
-               lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, MAX_SCHEDULE_TIMEOUT);
+               lret = reservation_object_wait_timeout_rcu(bo->resv, true, true,
+                                       nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
                if (!lret)
                        return -EBUSY;
                else if (lret < 0)
index c2a721a..b445ce9 100644 (file)
@@ -324,7 +324,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
        if (res->id != -1) {
 
                cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
-               if (unlikely(cmd == NULL)) {
+               if (unlikely(!cmd)) {
                        DRM_ERROR("Failed reserving FIFO space for surface "
                                  "destruction.\n");
                        return;
@@ -397,7 +397,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res)
 
        submit_size = vmw_surface_define_size(srf);
        cmd = vmw_fifo_reserve(dev_priv, submit_size);
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "creation.\n");
                ret = -ENOMEM;
@@ -446,11 +446,10 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res,
        uint8_t *cmd;
        struct vmw_private *dev_priv = res->dev_priv;
 
-       BUG_ON(val_buf->bo == NULL);
-
+       BUG_ON(!val_buf->bo);
        submit_size = vmw_surface_dma_size(srf);
        cmd = vmw_fifo_reserve(dev_priv, submit_size);
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "DMA.\n");
                return -ENOMEM;
@@ -538,7 +537,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res)
 
        submit_size = vmw_surface_destroy_size();
        cmd = vmw_fifo_reserve(dev_priv, submit_size);
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "eviction.\n");
                return -ENOMEM;
@@ -578,7 +577,7 @@ static int vmw_surface_init(struct vmw_private *dev_priv,
        int ret;
        struct vmw_resource *res = &srf->res;
 
-       BUG_ON(res_free == NULL);
+       BUG_ON(!res_free);
        if (!dev_priv->has_mob)
                vmw_fifo_resource_inc(dev_priv);
        ret = vmw_resource_init(dev_priv, res, true, res_free,
@@ -700,7 +699,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        struct drm_vmw_surface_create_req *req = &arg->req;
        struct drm_vmw_surface_arg *rep = &arg->rep;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-       struct drm_vmw_size __user *user_sizes;
        int ret;
        int i, j;
        uint32_t cur_bo_offset;
@@ -748,7 +746,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        }
 
        user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
-       if (unlikely(user_srf == NULL)) {
+       if (unlikely(!user_srf)) {
                ret = -ENOMEM;
                goto out_no_user_srf;
        }
@@ -763,29 +761,21 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
        memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
        srf->num_sizes = num_sizes;
        user_srf->size = size;
-
-       srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
-       if (unlikely(srf->sizes == NULL)) {
-               ret = -ENOMEM;
+       srf->sizes = memdup_user((struct drm_vmw_size __user *)(unsigned long)
+                                req->size_addr,
+                                sizeof(*srf->sizes) * srf->num_sizes);
+       if (IS_ERR(srf->sizes)) {
+               ret = PTR_ERR(srf->sizes);
                goto out_no_sizes;
        }
-       srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
-                              GFP_KERNEL);
-       if (unlikely(srf->offsets == NULL)) {
+       srf->offsets = kmalloc_array(srf->num_sizes,
+                                    sizeof(*srf->offsets),
+                                    GFP_KERNEL);
+       if (unlikely(!srf->offsets)) {
                ret = -ENOMEM;
                goto out_no_offsets;
        }
 
-       user_sizes = (struct drm_vmw_size __user *)(unsigned long)
-           req->size_addr;
-
-       ret = copy_from_user(srf->sizes, user_sizes,
-                            srf->num_sizes * sizeof(*srf->sizes));
-       if (unlikely(ret != 0)) {
-               ret = -EFAULT;
-               goto out_no_copy;
-       }
-
        srf->base_size = *srf->sizes;
        srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
        srf->multisample_count = 0;
@@ -923,7 +913,7 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
 
        ret = -EINVAL;
        base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
-       if (unlikely(base == NULL)) {
+       if (unlikely(!base)) {
                DRM_ERROR("Could not find surface to reference.\n");
                goto out_no_lookup;
        }
@@ -1069,7 +1059,7 @@ static int vmw_gb_surface_create(struct vmw_resource *res)
 
        cmd = vmw_fifo_reserve(dev_priv, submit_len);
        cmd2 = (typeof(cmd2))cmd;
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "creation.\n");
                ret = -ENOMEM;
@@ -1135,7 +1125,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res,
        submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
 
        cmd1 = vmw_fifo_reserve(dev_priv, submit_size);
-       if (unlikely(cmd1 == NULL)) {
+       if (unlikely(!cmd1)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "binding.\n");
                return -ENOMEM;
@@ -1185,7 +1175,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
 
        submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
        cmd = vmw_fifo_reserve(dev_priv, submit_size);
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "unbinding.\n");
                return -ENOMEM;
@@ -1244,7 +1234,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)
        vmw_binding_res_list_scrub(&res->binding_head);
 
        cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
-       if (unlikely(cmd == NULL)) {
+       if (unlikely(!cmd)) {
                DRM_ERROR("Failed reserving FIFO space for surface "
                          "destruction.\n");
                mutex_unlock(&dev_priv->binding_mutex);
@@ -1410,7 +1400,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
 
        user_srf = container_of(base, struct vmw_user_surface, prime.base);
        srf = &user_srf->srf;
-       if (srf->res.backup == NULL) {
+       if (!srf->res.backup) {
                DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
                goto out_bad_resource;
        }
@@ -1524,7 +1514,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
        }
 
        user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
-       if (unlikely(user_srf == NULL)) {
+       if (unlikely(!user_srf)) {
                ret = -ENOMEM;
                goto out_no_user_srf;
        }
index 8fd4bf7..818ea7d 100644 (file)
@@ -234,58 +234,6 @@ static __u8 pid0011_rdesc_fixed[] = {
        0xC0                /*  End Collection                  */
 };
 
-static __u8 pid0006_rdesc_fixed[] = {
-       0x05, 0x01,        /* Usage Page (Generic Desktop)      */
-       0x09, 0x04,        /* Usage (Joystick)                  */
-       0xA1, 0x01,        /* Collection (Application)          */
-       0xA1, 0x02,        /*   Collection (Logical)            */
-       0x75, 0x08,        /*     Report Size (8)               */
-       0x95, 0x05,        /*     Report Count (5)              */
-       0x15, 0x00,        /*     Logical Minimum (0)           */
-       0x26, 0xFF, 0x00,  /*     Logical Maximum (255)         */
-       0x35, 0x00,        /*     Physical Minimum (0)          */
-       0x46, 0xFF, 0x00,  /*     Physical Maximum (255)        */
-       0x09, 0x30,        /*     Usage (X)                     */
-       0x09, 0x33,        /*     Usage (Ry)                    */
-       0x09, 0x32,        /*     Usage (Z)                     */
-       0x09, 0x31,        /*     Usage (Y)                     */
-       0x09, 0x34,        /*     Usage (Ry)                    */
-       0x81, 0x02,        /*     Input (Variable)              */
-       0x75, 0x04,        /*     Report Size (4)               */
-       0x95, 0x01,        /*     Report Count (1)              */
-       0x25, 0x07,        /*     Logical Maximum (7)           */
-       0x46, 0x3B, 0x01,  /*     Physical Maximum (315)        */
-       0x65, 0x14,        /*     Unit (Centimeter)             */
-       0x09, 0x39,        /*     Usage (Hat switch)            */
-       0x81, 0x42,        /*     Input (Variable)              */
-       0x65, 0x00,        /*     Unit (None)                   */
-       0x75, 0x01,        /*     Report Size (1)               */
-       0x95, 0x0C,        /*     Report Count (12)             */
-       0x25, 0x01,        /*     Logical Maximum (1)           */
-       0x45, 0x01,        /*     Physical Maximum (1)          */
-       0x05, 0x09,        /*     Usage Page (Button)           */
-       0x19, 0x01,        /*     Usage Minimum (0x01)          */
-       0x29, 0x0C,        /*     Usage Maximum (0x0C)          */
-       0x81, 0x02,        /*     Input (Variable)              */
-       0x06, 0x00, 0xFF,  /*     Usage Page (Vendor Defined)   */
-       0x75, 0x01,        /*     Report Size (1)               */
-       0x95, 0x08,        /*     Report Count (8)              */
-       0x25, 0x01,        /*     Logical Maximum (1)           */
-       0x45, 0x01,        /*     Physical Maximum (1)          */
-       0x09, 0x01,        /*     Usage (0x01)                  */
-       0x81, 0x02,        /*     Input (Variable)              */
-       0xC0,              /*   End Collection                  */
-       0xA1, 0x02,        /*   Collection (Logical)            */
-       0x75, 0x08,        /*     Report Size (8)               */
-       0x95, 0x07,        /*     Report Count (7)              */
-       0x46, 0xFF, 0x00,  /*     Physical Maximum (255)        */
-       0x26, 0xFF, 0x00,  /*     Logical Maximum (255)         */
-       0x09, 0x02,        /*     Usage (0x02)                  */
-       0x91, 0x02,        /*     Output (Variable)             */
-       0xC0,              /*   End Collection                  */
-       0xC0               /* End Collection                    */
-};
-
 static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                                unsigned int *rsize)
 {
@@ -296,16 +244,34 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        *rsize = sizeof(pid0011_rdesc_fixed);
                }
                break;
-       case 0x0006:
-               if (*rsize == sizeof(pid0006_rdesc_fixed)) {
-                       rdesc = pid0006_rdesc_fixed;
-                       *rsize = sizeof(pid0006_rdesc_fixed);
-               }
-               break;
        }
        return rdesc;
 }
 
+#define map_abs(c)      hid_map_usage(hi, usage, bit, max, EV_ABS, (c))
+#define map_rel(c)      hid_map_usage(hi, usage, bit, max, EV_REL, (c))
+
+static int dr_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+                           struct hid_field *field, struct hid_usage *usage,
+                           unsigned long **bit, int *max)
+{
+       switch (usage->hid) {
+       /*
+        * revert to the old hid-input behavior where axes
+        * can be randomly assigned when hid->usage is reused.
+        */
+       case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
+       case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
+               if (field->flags & HID_MAIN_ITEM_RELATIVE)
+                       map_rel(usage->hid & 0xf);
+               else
+                       map_abs(usage->hid & 0xf);
+               return 1;
+       }
+
+       return 0;
+}
+
 static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
@@ -352,6 +318,7 @@ static struct hid_driver dr_driver = {
        .id_table = dr_devices,
        .report_fixup = dr_report_fixup,
        .probe = dr_probe,
+       .input_mapping = dr_input_mapping,
 };
 module_hid_driver(dr_driver);
 
index cd59c79..6cfb5ca 100644 (file)
@@ -64,6 +64,9 @@
 #define USB_VENDOR_ID_AKAI             0x2011
 #define USB_DEVICE_ID_AKAI_MPKMINI2    0x0715
 
+#define USB_VENDOR_ID_AKAI_09E8                0x09E8
+#define USB_DEVICE_ID_AKAI_09E8_MIDIMIX        0x0031
+
 #define USB_VENDOR_ID_ALCOR            0x058f
 #define USB_DEVICE_ID_ALCOR_USBRS232   0x9720
 
index d8d55f3..d3e1ab1 100644 (file)
@@ -100,6 +100,7 @@ struct hidled_device {
        const struct hidled_config *config;
        struct hid_device       *hdev;
        struct hidled_rgb       *rgb;
+       u8                      *buf;
        struct mutex            lock;
 };
 
@@ -118,13 +119,19 @@ static int hidled_send(struct hidled_device *ldev, __u8 *buf)
 
        mutex_lock(&ldev->lock);
 
+       /*
+        * buffer provided to hid_hw_raw_request must not be on the stack
+        * and must not be part of a data structure
+        */
+       memcpy(ldev->buf, buf, ldev->config->report_size);
+
        if (ldev->config->report_type == RAW_REQUEST)
-               ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
+               ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
                                         ldev->config->report_size,
                                         HID_FEATURE_REPORT,
                                         HID_REQ_SET_REPORT);
        else if (ldev->config->report_type == OUTPUT_REPORT)
-               ret = hid_hw_output_report(ldev->hdev, buf,
+               ret = hid_hw_output_report(ldev->hdev, ldev->buf,
                                           ldev->config->report_size);
        else
                ret = -EINVAL;
@@ -147,17 +154,21 @@ static int hidled_recv(struct hidled_device *ldev, __u8 *buf)
 
        mutex_lock(&ldev->lock);
 
-       ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
+       memcpy(ldev->buf, buf, ldev->config->report_size);
+
+       ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
                                 ldev->config->report_size,
                                 HID_FEATURE_REPORT,
                                 HID_REQ_SET_REPORT);
        if (ret < 0)
                goto err;
 
-       ret = hid_hw_raw_request(ldev->hdev, buf[0], buf,
+       ret = hid_hw_raw_request(ldev->hdev, buf[0], ldev->buf,
                                 ldev->config->report_size,
                                 HID_FEATURE_REPORT,
                                 HID_REQ_GET_REPORT);
+
+       memcpy(buf, ldev->buf, ldev->config->report_size);
 err:
        mutex_unlock(&ldev->lock);
 
@@ -447,6 +458,10 @@ static int hidled_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (!ldev)
                return -ENOMEM;
 
+       ldev->buf = devm_kmalloc(&hdev->dev, MAX_REPORT_SIZE, GFP_KERNEL);
+       if (!ldev->buf)
+               return -ENOMEM;
+
        ret = hid_parse(hdev);
        if (ret)
                return ret;
index 0a0eca5..354d49e 100644 (file)
@@ -56,6 +56,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_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 4aa3cb6..bcd0630 100644 (file)
@@ -314,10 +314,14 @@ static void heartbeat_onchannelcallback(void *context)
        u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
        struct icmsg_negotiate *negop = NULL;
 
-       vmbus_recvpacket(channel, hbeat_txf_buf,
-                        PAGE_SIZE, &recvlen, &requestid);
+       while (1) {
+
+               vmbus_recvpacket(channel, hbeat_txf_buf,
+                                PAGE_SIZE, &recvlen, &requestid);
+
+               if (!recvlen)
+                       break;
 
-       if (recvlen > 0) {
                icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
                                sizeof(struct vmbuspipe_hdr)];
 
index 98114ce..2fe1828 100644 (file)
@@ -194,10 +194,10 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
                 * 0.5'C per two measurement cycles thus ignore possible
                 * but unlikely aliasing error on lsb reading. --Grant
                 */
-               data->temp = ((i2c_smbus_read_byte_data(client,
+               data->temp = (i2c_smbus_read_byte_data(client,
                                        ADM9240_REG_TEMP) << 8) |
                                        i2c_smbus_read_byte_data(client,
-                                       ADM9240_REG_TEMP_CONF)) / 128;
+                                       ADM9240_REG_TEMP_CONF);
 
                for (i = 0; i < 2; i++) { /* read fans */
                        data->fan[i] = i2c_smbus_read_byte_data(client,
@@ -263,7 +263,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *dummy,
                char *buf)
 {
        struct adm9240_data *data = adm9240_update_device(dev);
-       return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */
+       return sprintf(buf, "%d\n", data->temp / 128 * 500); /* 9-bit value */
 }
 
 static ssize_t show_max(struct device *dev, struct device_attribute *devattr,
index bef84e0..c1b9275 100644 (file)
@@ -268,11 +268,13 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel,
                             long *val)
 {
        struct max31790_data *data = max31790_update_device(dev);
-       u8 fan_config = data->fan_config[channel];
+       u8 fan_config;
 
        if (IS_ERR(data))
                return PTR_ERR(data);
 
+       fan_config = data->fan_config[channel];
+
        switch (attr) {
        case hwmon_pwm_input:
                *val = data->pwm[channel] >> 8;
index 6d94e2e..d252276 100644 (file)
@@ -79,12 +79,12 @@ config I2C_AMD8111
 
 config I2C_HIX5HD2
        tristate "Hix5hd2 high-speed I2C driver"
-       depends on ARCH_HIX5HD2 || COMPILE_TEST
+       depends on ARCH_HISI || ARCH_HIX5HD2 || COMPILE_TEST
        help
-         Say Y here to include support for high-speed I2C controller in the
-         Hisilicon based hix5hd2 SoCs.
+         Say Y here to include support for the high-speed I2C controller
+         used in HiSilicon hix5hd2 SoCs.
 
-         This driver can also be built as a module.  If so, the module
+         This driver can also be built as a module. If so, the module
          will be called i2c-hix5hd2.
 
 config I2C_I801
@@ -589,10 +589,10 @@ config I2C_IMG
 
 config I2C_IMX
        tristate "IMX I2C interface"
-       depends on ARCH_MXC || ARCH_LAYERSCAPE
+       depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE
        help
          Say Y here if you want to use the IIC bus controller on
-         the Freescale i.MX/MXC or Layerscape processors.
+         the Freescale i.MX/MXC, Layerscape or ColdFire processors.
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-imx.
index 1fe93c4..11e866d 100644 (file)
@@ -95,6 +95,9 @@
 #define DW_IC_STATUS_TFE               BIT(2)
 #define DW_IC_STATUS_MST_ACTIVITY      BIT(5)
 
+#define DW_IC_SDA_HOLD_RX_SHIFT                16
+#define DW_IC_SDA_HOLD_RX_MASK         GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT)
+
 #define DW_IC_ERR_TX_ABRT      0x1
 
 #define DW_IC_TAR_10BITADDR_MASTER BIT(12)
@@ -420,12 +423,20 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        /* Configure SDA Hold Time if required */
        reg = dw_readl(dev, DW_IC_COMP_VERSION);
        if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
-               if (dev->sda_hold_time) {
-                       dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
-               } else {
+               if (!dev->sda_hold_time) {
                        /* Keep previous hold time setting if no one set it */
                        dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
                }
+               /*
+                * Workaround for avoiding TX arbitration lost in case I2C
+                * slave pulls SDA down "too quickly" after falling egde of
+                * SCL by enabling non-zero SDA RX hold. Specification says it
+                * extends incoming SDA low to high transition while SCL is
+                * high but it apprears to help also above issue.
+                */
+               if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
+                       dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
+               dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
        } else {
                dev_warn(dev->dev,
                        "Hardware too old to adjust SDA hold time.\n");
index 9604024..49f2084 100644 (file)
@@ -368,6 +368,7 @@ static const struct of_device_id dc_i2c_match[] = {
        { .compatible = "cnxt,cx92755-i2c" },
        { },
 };
+MODULE_DEVICE_TABLE(of, dc_i2c_match);
 
 static struct platform_driver dc_i2c_driver = {
        .probe   = dc_i2c_probe,
index 08847e8..eb3627f 100644 (file)
 #define SMBHSTCFG_HST_EN       1
 #define SMBHSTCFG_SMB_SMI_EN   2
 #define SMBHSTCFG_I2C_EN       4
+#define SMBHSTCFG_SPD_WD       0x10
 
 /* TCO configuration bits for TCOCTL */
 #define TCOCTL_EN              0x0100
@@ -865,9 +866,16 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
                block = 1;
                break;
        case I2C_SMBUS_I2C_BLOCK_DATA:
-               /* NB: page 240 of ICH5 datasheet shows that the R/#W
-                * bit should be cleared here, even when reading */
-               outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
+               /*
+                * NB: page 240 of ICH5 datasheet shows that the R/#W
+                * bit should be cleared here, even when reading.
+                * However if SPD Write Disable is set (Lynx Point and later),
+                * the read will fail if we don't set the R/#W bit.
+                */
+               outb_p(((addr & 0x7f) << 1) |
+                      ((priv->original_hstcfg & SMBHSTCFG_SPD_WD) ?
+                       (read_write & 0x01) : 0),
+                      SMBHSTADD(priv));
                if (read_write == I2C_SMBUS_READ) {
                        /* NB: page 240 of ICH5 datasheet also shows
                         * that DATA1 is the cmd field when reading */
@@ -1573,6 +1581,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                /* Disable SMBus interrupt feature if SMBus using SMI# */
                priv->features &= ~FEATURE_IRQ;
        }
+       if (temp & SMBHSTCFG_SPD_WD)
+               dev_info(&dev->dev, "SPD Write Disable is set\n");
 
        /* Clear special mode bits */
        if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
index 592a8f2..47fc1f1 100644 (file)
@@ -1009,10 +1009,13 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
        rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0);
        rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0);
 
-       if (!gpio_is_valid(rinfo->sda_gpio) ||
-           !gpio_is_valid(rinfo->scl_gpio) ||
-           IS_ERR(i2c_imx->pinctrl_pins_default) ||
-           IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
+       if (rinfo->sda_gpio == -EPROBE_DEFER ||
+           rinfo->scl_gpio == -EPROBE_DEFER) {
+               return -EPROBE_DEFER;
+       } else if (!gpio_is_valid(rinfo->sda_gpio) ||
+                  !gpio_is_valid(rinfo->scl_gpio) ||
+                  IS_ERR(i2c_imx->pinctrl_pins_default) ||
+                  IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
                dev_dbg(&pdev->dev, "recovery information incomplete\n");
                return 0;
        }
index b8ea621..30132c3 100644 (file)
@@ -729,6 +729,7 @@ static const struct of_device_id jz4780_i2c_of_matches[] = {
        { .compatible = "ingenic,jz4780-i2c", },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, jz4780_i2c_of_matches);
 
 static int jz4780_i2c_probe(struct platform_device *pdev)
 {
index 50702c7..df22066 100644 (file)
@@ -694,6 +694,8 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
        t_calc->div_low--;
        t_calc->div_high--;
 
+       /* Give the tuning value 0, that would not update con register */
+       t_calc->tuning = 0;
        /* Maximum divider supported by hw is 0xffff */
        if (t_calc->div_low > 0xffff) {
                t_calc->div_low = 0xffff;
index 263685c..05cf192 100644 (file)
@@ -105,7 +105,7 @@ struct slimpro_i2c_dev {
        struct mbox_chan *mbox_chan;
        struct mbox_client mbox_client;
        struct completion rd_complete;
-       u8 dma_buffer[I2C_SMBUS_BLOCK_MAX];
+       u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* dma_buffer[0] is used for length */
        u32 *resp_msg;
 };
 
index 2a972ed..e29ff37 100644 (file)
@@ -426,6 +426,7 @@ static const struct of_device_id xlp9xx_i2c_of_match[] = {
        { .compatible = "netlogic,xlp980-i2c", },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, xlp9xx_i2c_of_match);
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xlp9xx_i2c_acpi_ids[] = {
index 0968f59..ad17d88 100644 (file)
@@ -358,6 +358,7 @@ static const struct of_device_id xlr_i2c_dt_ids[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(of, xlr_i2c_dt_ids);
 
 static int xlr_i2c_probe(struct platform_device *pdev)
 {
index 5ab6721..1704fc8 100644 (file)
@@ -1681,6 +1681,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
 static void of_i2c_register_devices(struct i2c_adapter *adap)
 {
        struct device_node *bus, *node;
+       struct i2c_client *client;
 
        /* Only register child devices if the adapter has a node pointer set */
        if (!adap->dev.of_node)
@@ -1695,7 +1696,14 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
        for_each_available_child_of_node(bus, node) {
                if (of_node_test_and_set_flag(node, OF_POPULATED))
                        continue;
-               of_i2c_register_device(adap, node);
+
+               client = of_i2c_register_device(adap, node);
+               if (IS_ERR(client)) {
+                       dev_warn(&adap->dev,
+                                "Failed to create I2C device for %s\n",
+                                node->full_name);
+                       of_node_clear_flag(node, OF_POPULATED);
+               }
        }
 
        of_node_put(bus);
@@ -2299,6 +2307,7 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
                if (IS_ERR(client)) {
                        dev_err(&adap->dev, "failed to create client for '%s'\n",
                                 rd->dn->full_name);
+                       of_node_clear_flag(rd->dn, OF_POPULATED);
                        return notifier_from_errno(PTR_ERR(client));
                }
                break;
index 7edcf32..99c0514 100644 (file)
@@ -437,6 +437,8 @@ config STX104
 config TI_ADC081C
        tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
        depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
        help
          If you say yes here you get support for Texas Instruments ADC081C,
          ADC101C and ADC121C ADC chips.
index bd321b3..ef761a5 100644 (file)
@@ -213,13 +213,14 @@ static int atlas_check_ec_calibration(struct atlas_data *data)
        struct device *dev = &data->client->dev;
        int ret;
        unsigned int val;
+       __be16  rval;
 
-       ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &val, 2);
+       ret = regmap_bulk_read(data->regmap, ATLAS_REG_EC_PROBE, &rval, 2);
        if (ret)
                return ret;
 
-       dev_info(dev, "probe set to K = %d.%.2d", be16_to_cpu(val) / 100,
-                                                be16_to_cpu(val) % 100);
+       val = be16_to_cpu(rval);
+       dev_info(dev, "probe set to K = %d.%.2d", val / 100, val % 100);
 
        ret = regmap_read(data->regmap, ATLAS_REG_EC_CALIB_STATUS, &val);
        if (ret)
index 39dd202..066161a 100644 (file)
@@ -123,22 +123,24 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
 {
        unsigned int storage_bytes = data->chip->read_size;
        unsigned int shift = chan->scan_type.shift + (chan->address * 8);
-       unsigned int buf;
+       __be16 buf16;
+       __be32 buf32;
        int ret;
 
-       ret = spi_read(data->spi, (void *) &buf, storage_bytes);
-       if (ret)
-               return ret;
-
        switch (storage_bytes) {
        case 2:
-               *val = be16_to_cpu(buf);
+               ret = spi_read(data->spi, (void *)&buf16, storage_bytes);
+               *val = be16_to_cpu(buf16);
                break;
        case 4:
-               *val = be32_to_cpu(buf);
+               ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
+               *val = be32_to_cpu(buf32);
                break;
        }
 
+       if (ret)
+               return ret;
+
        /* check to be sure this is a valid reading */
        if (*val & data->chip->status_bit)
                return -EINVAL;
index c68746c..224ad27 100644 (file)
@@ -94,6 +94,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        unsigned long dma_attrs = 0;
        struct scatterlist *sg, *sg_list_start;
        int need_release = 0;
+       unsigned int gup_flags = FOLL_WRITE;
 
        if (dmasync)
                dma_attrs |= DMA_ATTR_WRITE_BARRIER;
@@ -183,6 +184,9 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        if (ret)
                goto out;
 
+       if (!umem->writable)
+               gup_flags |= FOLL_FORCE;
+
        need_release = 1;
        sg_list_start = umem->sg_head.sgl;
 
@@ -190,7 +194,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
                ret = get_user_pages(cur_base,
                                     min_t(unsigned long, npages,
                                           PAGE_SIZE / sizeof (struct page *)),
-                                    1, !umem->writable, page_list, vma_list);
+                                    gup_flags, page_list, vma_list);
 
                if (ret < 0)
                        goto out;
index 75077a0..1f0fe32 100644 (file)
@@ -527,6 +527,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
        u64 off;
        int j, k, ret = 0, start_idx, npages = 0;
        u64 base_virt_addr;
+       unsigned int flags = 0;
 
        if (access_mask == 0)
                return -EINVAL;
@@ -556,6 +557,9 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
                goto out_put_task;
        }
 
+       if (access_mask & ODP_WRITE_ALLOWED_BIT)
+               flags |= FOLL_WRITE;
+
        start_idx = (user_virt - ib_umem_start(umem)) >> PAGE_SHIFT;
        k = start_idx;
 
@@ -574,8 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
                 */
                npages = get_user_pages_remote(owning_process, owning_mm,
                                user_virt, gup_num_pages,
-                               access_mask & ODP_WRITE_ALLOWED_BIT,
-                               0, local_page_list, NULL);
+                               flags, local_page_list, NULL);
                up_read(&owning_mm->mmap_sem);
 
                if (npages < 0)
index 2217477..63036c7 100644 (file)
@@ -1019,7 +1019,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
        if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
                resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
-       resp.cache_line_size = L1_CACHE_BYTES;
+       resp.cache_line_size = cache_line_size();
        resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
        resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
        resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
index 41f4c2a..7ce97da 100644 (file)
@@ -52,7 +52,6 @@ enum {
 
 enum {
        MLX5_IB_SQ_STRIDE       = 6,
-       MLX5_IB_CACHE_LINE_SIZE = 64,
 };
 
 static const u32 mlx5_ib_opcode[] = {
index 6c00d04..c6fe89d 100644 (file)
@@ -472,7 +472,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
                goto out;
        }
 
-       ret = get_user_pages(uaddr & PAGE_MASK, 1, 1, 0, pages, NULL);
+       ret = get_user_pages(uaddr & PAGE_MASK, 1, FOLL_WRITE, pages, NULL);
        if (ret < 0)
                goto out;
 
index 7c06d85..6c9f392 100644 (file)
@@ -2,6 +2,7 @@ config INFINIBAND_QEDR
        tristate "QLogic RoCE driver"
        depends on 64BIT && QEDE
        select QED_LL2
+       select QED_RDMA
        ---help---
          This driver provides low-level InfiniBand over Ethernet
          support for QLogic QED host channel adapters (HCAs).
index 2d2b94f..75f0862 100644 (file)
@@ -67,7 +67,8 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
 
        for (got = 0; got < num_pages; got += ret) {
                ret = get_user_pages(start_page + got * PAGE_SIZE,
-                                    num_pages - got, 1, 1,
+                                    num_pages - got,
+                                    FOLL_WRITE | FOLL_FORCE,
                                     p + got, NULL);
                if (ret < 0)
                        goto bail_release;
index a0b6ebe..1ccee6e 100644 (file)
@@ -111,6 +111,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
        int i;
        int flags;
        dma_addr_t pa;
+       unsigned int gup_flags;
 
        if (!can_do_mlock())
                return -EPERM;
@@ -135,6 +136,8 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
 
        flags = IOMMU_READ | IOMMU_CACHE;
        flags |= (writable) ? IOMMU_WRITE : 0;
+       gup_flags = FOLL_WRITE;
+       gup_flags |= (writable) ? 0 : FOLL_FORCE;
        cur_base = addr & PAGE_MASK;
        ret = 0;
 
@@ -142,7 +145,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
                ret = get_user_pages(cur_base,
                                        min_t(unsigned long, npages,
                                        PAGE_SIZE / sizeof(struct page *)),
-                                       1, !writable, page_list, NULL);
+                                       gup_flags, page_list, NULL);
 
                if (ret < 0)
                        goto out;
index 7b8d2d9..da12717 100644 (file)
@@ -63,6 +63,8 @@ enum ipoib_flush_level {
 
 enum {
        IPOIB_ENCAP_LEN           = 4,
+       IPOIB_PSEUDO_LEN          = 20,
+       IPOIB_HARD_LEN            = IPOIB_ENCAP_LEN + IPOIB_PSEUDO_LEN,
 
        IPOIB_UD_HEAD_SIZE        = IB_GRH_BYTES + IPOIB_ENCAP_LEN,
        IPOIB_UD_RX_SG            = 2, /* max buffer needed for 4K mtu */
@@ -134,15 +136,21 @@ struct ipoib_header {
        u16     reserved;
 };
 
-struct ipoib_cb {
-       struct qdisc_skb_cb     qdisc_cb;
-       u8                      hwaddr[INFINIBAND_ALEN];
+struct ipoib_pseudo_header {
+       u8      hwaddr[INFINIBAND_ALEN];
 };
 
-static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb)
+static inline void skb_add_pseudo_hdr(struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb));
-       return (struct ipoib_cb *)skb->cb;
+       char *data = skb_push(skb, IPOIB_PSEUDO_LEN);
+
+       /*
+        * only the ipoib header is present now, make room for a dummy
+        * pseudo header and set skb field accordingly
+        */
+       memset(data, 0, IPOIB_PSEUDO_LEN);
+       skb_reset_mac_header(skb);
+       skb_pull(skb, IPOIB_HARD_LEN);
 }
 
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
index 4ad297d..339a1ee 100644 (file)
@@ -63,6 +63,8 @@ MODULE_PARM_DESC(cm_data_debug_level,
 #define IPOIB_CM_RX_DELAY       (3 * 256 * HZ)
 #define IPOIB_CM_RX_UPDATE_MASK (0x3)
 
+#define IPOIB_CM_RX_RESERVE     (ALIGN(IPOIB_HARD_LEN, 16) - IPOIB_ENCAP_LEN)
+
 static struct ib_qp_attr ipoib_cm_err_attr = {
        .qp_state = IB_QPS_ERR
 };
@@ -146,15 +148,15 @@ static struct sk_buff *ipoib_cm_alloc_rx_skb(struct net_device *dev,
        struct sk_buff *skb;
        int i;
 
-       skb = dev_alloc_skb(IPOIB_CM_HEAD_SIZE + 12);
+       skb = dev_alloc_skb(ALIGN(IPOIB_CM_HEAD_SIZE + IPOIB_PSEUDO_LEN, 16));
        if (unlikely(!skb))
                return NULL;
 
        /*
-        * IPoIB adds a 4 byte header. So we need 12 more bytes to align the
+        * IPoIB adds a IPOIB_ENCAP_LEN byte header, this will align the
         * IP header to a multiple of 16.
         */
-       skb_reserve(skb, 12);
+       skb_reserve(skb, IPOIB_CM_RX_RESERVE);
 
        mapping[0] = ib_dma_map_single(priv->ca, skb->data, IPOIB_CM_HEAD_SIZE,
                                       DMA_FROM_DEVICE);
@@ -624,9 +626,9 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        if (wc->byte_len < IPOIB_CM_COPYBREAK) {
                int dlen = wc->byte_len;
 
-               small_skb = dev_alloc_skb(dlen + 12);
+               small_skb = dev_alloc_skb(dlen + IPOIB_CM_RX_RESERVE);
                if (small_skb) {
-                       skb_reserve(small_skb, 12);
+                       skb_reserve(small_skb, IPOIB_CM_RX_RESERVE);
                        ib_dma_sync_single_for_cpu(priv->ca, rx_ring[wr_id].mapping[0],
                                                   dlen, DMA_FROM_DEVICE);
                        skb_copy_from_linear_data(skb, small_skb->data, dlen);
@@ -663,8 +665,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
 
 copied:
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-       skb_reset_mac_header(skb);
-       skb_pull(skb, IPOIB_ENCAP_LEN);
+       skb_add_pseudo_hdr(skb);
 
        ++dev->stats.rx_packets;
        dev->stats.rx_bytes += skb->len;
index be11d5d..830fecb 100644 (file)
@@ -128,16 +128,15 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
 
        buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
 
-       skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN);
+       skb = dev_alloc_skb(buf_size + IPOIB_HARD_LEN);
        if (unlikely(!skb))
                return NULL;
 
        /*
-        * IB will leave a 40 byte gap for a GRH and IPoIB adds a 4 byte
-        * header.  So we need 4 more bytes to get to 48 and align the
-        * IP header to a multiple of 16.
+        * the IP header will be at IPOIP_HARD_LEN + IB_GRH_BYTES, that is
+        * 64 bytes aligned
         */
-       skb_reserve(skb, 4);
+       skb_reserve(skb, sizeof(struct ipoib_pseudo_header));
 
        mapping = priv->rx_ring[id].mapping;
        mapping[0] = ib_dma_map_single(priv->ca, skb->data, buf_size,
@@ -253,8 +252,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        skb_pull(skb, IB_GRH_BYTES);
 
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
-       skb_reset_mac_header(skb);
-       skb_pull(skb, IPOIB_ENCAP_LEN);
+       skb_add_pseudo_hdr(skb);
 
        ++dev->stats.rx_packets;
        dev->stats.rx_bytes += skb->len;
index 5636fc3..b58d9dc 100644 (file)
@@ -925,9 +925,12 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
                                ipoib_neigh_free(neigh);
                                goto err_drop;
                        }
-                       if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
+                       if (skb_queue_len(&neigh->queue) <
+                           IPOIB_MAX_PATH_REC_QUEUE) {
+                               /* put pseudoheader back on for next time */
+                               skb_push(skb, IPOIB_PSEUDO_LEN);
                                __skb_queue_tail(&neigh->queue, skb);
-                       else {
+                       else {
                                ipoib_warn(priv, "queue length limit %d. Packet drop.\n",
                                           skb_queue_len(&neigh->queue));
                                goto err_drop;
@@ -964,7 +967,7 @@ err_drop:
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
-                            struct ipoib_cb *cb)
+                            struct ipoib_pseudo_header *phdr)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
@@ -972,16 +975,18 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       path = __path_find(dev, cb->hwaddr + 4);
+       path = __path_find(dev, phdr->hwaddr + 4);
        if (!path || !path->valid) {
                int new_path = 0;
 
                if (!path) {
-                       path = path_rec_create(dev, cb->hwaddr + 4);
+                       path = path_rec_create(dev, phdr->hwaddr + 4);
                        new_path = 1;
                }
                if (path) {
                        if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+                               /* put pseudoheader back on for next time */
+                               skb_push(skb, IPOIB_PSEUDO_LEN);
                                __skb_queue_tail(&path->queue, skb);
                        } else {
                                ++dev->stats.tx_dropped;
@@ -1009,10 +1014,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                          be16_to_cpu(path->pathrec.dlid));
 
                spin_unlock_irqrestore(&priv->lock, flags);
-               ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
+               ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
                return;
        } else if ((path->query || !path_rec_start(dev, path)) &&
                   skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+               /* put pseudoheader back on for next time */
+               skb_push(skb, IPOIB_PSEUDO_LEN);
                __skb_queue_tail(&path->queue, skb);
        } else {
                ++dev->stats.tx_dropped;
@@ -1026,13 +1033,15 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_neigh *neigh;
-       struct ipoib_cb *cb = ipoib_skb_cb(skb);
+       struct ipoib_pseudo_header *phdr;
        struct ipoib_header *header;
        unsigned long flags;
 
+       phdr = (struct ipoib_pseudo_header *) skb->data;
+       skb_pull(skb, sizeof(*phdr));
        header = (struct ipoib_header *) skb->data;
 
-       if (unlikely(cb->hwaddr[4] == 0xff)) {
+       if (unlikely(phdr->hwaddr[4] == 0xff)) {
                /* multicast, arrange "if" according to probability */
                if ((header->proto != htons(ETH_P_IP)) &&
                    (header->proto != htons(ETH_P_IPV6)) &&
@@ -1045,13 +1054,13 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        return NETDEV_TX_OK;
                }
                /* Add in the P_Key for multicast*/
-               cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
-               cb->hwaddr[9] = priv->pkey & 0xff;
+               phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+               phdr->hwaddr[9] = priv->pkey & 0xff;
 
-               neigh = ipoib_neigh_get(dev, cb->hwaddr);
+               neigh = ipoib_neigh_get(dev, phdr->hwaddr);
                if (likely(neigh))
                        goto send_using_neigh;
-               ipoib_mcast_send(dev, cb->hwaddr, skb);
+               ipoib_mcast_send(dev, phdr->hwaddr, skb);
                return NETDEV_TX_OK;
        }
 
@@ -1060,16 +1069,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
        case htons(ETH_P_IP):
        case htons(ETH_P_IPV6):
        case htons(ETH_P_TIPC):
-               neigh = ipoib_neigh_get(dev, cb->hwaddr);
+               neigh = ipoib_neigh_get(dev, phdr->hwaddr);
                if (unlikely(!neigh)) {
-                       neigh_add_path(skb, cb->hwaddr, dev);
+                       neigh_add_path(skb, phdr->hwaddr, dev);
                        return NETDEV_TX_OK;
                }
                break;
        case htons(ETH_P_ARP):
        case htons(ETH_P_RARP):
                /* for unicast ARP and RARP should always perform path find */
-               unicast_arp_send(skb, dev, cb);
+               unicast_arp_send(skb, dev, phdr);
                return NETDEV_TX_OK;
        default:
                /* ethertype not supported by IPoIB */
@@ -1086,11 +1095,13 @@ send_using_neigh:
                        goto unref;
                }
        } else if (neigh->ah) {
-               ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(cb->hwaddr));
+               ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(phdr->hwaddr));
                goto unref;
        }
 
        if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+               /* put pseudoheader back on for next time */
+               skb_push(skb, sizeof(*phdr));
                spin_lock_irqsave(&priv->lock, flags);
                __skb_queue_tail(&neigh->queue, skb);
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -1122,8 +1133,8 @@ static int ipoib_hard_header(struct sk_buff *skb,
                             unsigned short type,
                             const void *daddr, const void *saddr, unsigned len)
 {
+       struct ipoib_pseudo_header *phdr;
        struct ipoib_header *header;
-       struct ipoib_cb *cb = ipoib_skb_cb(skb);
 
        header = (struct ipoib_header *) skb_push(skb, sizeof *header);
 
@@ -1132,12 +1143,13 @@ static int ipoib_hard_header(struct sk_buff *skb,
 
        /*
         * we don't rely on dst_entry structure,  always stuff the
-        * destination address into skb->cb so we can figure out where
+        * destination address into skb hard header so we can figure out where
         * to send the packet later.
         */
-       memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
+       phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr));
+       memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
 
-       return sizeof *header;
+       return IPOIB_HARD_LEN;
 }
 
 static void ipoib_set_mcast_list(struct net_device *dev)
@@ -1759,7 +1771,7 @@ void ipoib_setup(struct net_device *dev)
 
        dev->flags              |= IFF_BROADCAST | IFF_MULTICAST;
 
-       dev->hard_header_len     = IPOIB_ENCAP_LEN;
+       dev->hard_header_len     = IPOIB_HARD_LEN;
        dev->addr_len            = INFINIBAND_ALEN;
        dev->type                = ARPHRD_INFINIBAND;
        dev->tx_queue_len        = ipoib_sendq_size * 2;
index d3394b6..1909dd2 100644 (file)
@@ -796,9 +796,11 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
                        __ipoib_mcast_add(dev, mcast);
                        list_add_tail(&mcast->list, &priv->multicast_list);
                }
-               if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
+               if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE) {
+                       /* put pseudoheader back on for next time */
+                       skb_push(skb, sizeof(struct ipoib_pseudo_header));
                        skb_queue_tail(&mcast->pkt_queue, skb);
-               else {
+               else {
                        ++dev->stats.tx_dropped;
                        dev_kfree_skb_any(skb);
                }
index c0e7b62..1210244 100644 (file)
@@ -178,7 +178,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
                       idev->id_vendor, idev->id_device);
 }
 
-ipack_device_attr(id_format, "0x%hhu\n");
+ipack_device_attr(id_format, "0x%hhx\n");
 
 static DEVICE_ATTR_RO(id);
 static DEVICE_ATTR_RO(id_device);
index 82b0b5d..bc0af33 100644 (file)
@@ -158,8 +158,8 @@ config PIC32_EVIC
        select IRQ_DOMAIN
 
 config JCORE_AIC
-       bool "J-Core integrated AIC"
-       depends on OF && (SUPERH || COMPILE_TEST)
+       bool "J-Core integrated AIC" if COMPILE_TEST
+       depends on OF
        select IRQ_DOMAIN
        help
          Support for the J-Core integrated AIC.
index efbf0e4..2a7a388 100644 (file)
@@ -85,7 +85,7 @@ static void nps400_irq_eoi_global(struct irq_data *irqd)
        nps_ack_gic();
 }
 
-static void nps400_irq_eoi(struct irq_data *irqd)
+static void nps400_irq_ack(struct irq_data *irqd)
 {
        unsigned int __maybe_unused irq = irqd_to_hwirq(irqd);
 
@@ -103,7 +103,7 @@ static struct irq_chip nps400_irq_chip_percpu = {
        .name           = "NPS400 IC",
        .irq_mask       = nps400_irq_mask,
        .irq_unmask     = nps400_irq_unmask,
-       .irq_eoi        = nps400_irq_eoi,
+       .irq_ack        = nps400_irq_ack,
 };
 
 static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
@@ -135,7 +135,7 @@ static const struct irq_domain_ops nps400_irq_ops = {
 static int __init nps400_of_init(struct device_node *node,
                                 struct device_node *parent)
 {
-       static struct irq_domain *nps400_root_domain;
+       struct irq_domain *nps400_root_domain;
 
        if (parent) {
                pr_err("DeviceTree incore ic not a root irq controller\n");
index 003495d..c5dee30 100644 (file)
@@ -1023,7 +1023,7 @@ static void its_free_tables(struct its_node *its)
 
 static int its_alloc_tables(struct its_node *its)
 {
-       u64 typer = readq_relaxed(its->base + GITS_TYPER);
+       u64 typer = gic_read_typer(its->base + GITS_TYPER);
        u32 ids = GITS_TYPER_DEVBITS(typer);
        u64 shr = GITS_BASER_InnerShareable;
        u64 cache = GITS_BASER_WaWb;
@@ -1198,7 +1198,7 @@ static void its_cpu_init_collection(void)
                 * We now have to bind each collection to its target
                 * redistributor.
                 */
-               if (readq_relaxed(its->base + GITS_TYPER) & GITS_TYPER_PTA) {
+               if (gic_read_typer(its->base + GITS_TYPER) & GITS_TYPER_PTA) {
                        /*
                         * This ITS wants the physical address of the
                         * redistributor.
@@ -1208,7 +1208,7 @@ static void its_cpu_init_collection(void)
                        /*
                         * This ITS wants a linear CPU number.
                         */
-                       target = readq_relaxed(gic_data_rdist_rd_base() + GICR_TYPER);
+                       target = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
                        target = GICR_TYPER_CPU_NUMBER(target) << 16;
                }
 
@@ -1691,7 +1691,7 @@ static int __init its_probe_one(struct resource *res,
        INIT_LIST_HEAD(&its->its_device_list);
        its->base = its_base;
        its->phys_base = res->start;
-       its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+       its->ite_size = ((gic_read_typer(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
        its->numa_node = numa_node;
 
        its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
@@ -1763,7 +1763,7 @@ out_unmap:
 
 static bool gic_rdists_supports_plpis(void)
 {
-       return !!(readl_relaxed(gic_data_rdist_rd_base() + GICR_TYPER) & GICR_TYPER_PLPIS);
+       return !!(gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER) & GICR_TYPER_PLPIS);
 }
 
 int its_cpu_init(void)
index 9b81bd8..19d642e 100644 (file)
@@ -153,7 +153,7 @@ static void gic_enable_redist(bool enable)
                        return; /* No PM support in this redistributor */
        }
 
-       while (count--) {
+       while (--count) {
                val = readl_relaxed(rbase + GICR_WAKER);
                if (enable ^ (bool)(val & GICR_WAKER_ChildrenAsleep))
                        break;
index 58e5b4e..d6c404b 100644 (file)
@@ -1279,7 +1279,7 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
                 */
                *base += 0xf000;
                cpuif_res.start += 0xf000;
-               pr_warn("GIC: Adjusting CPU interface base to %pa",
+               pr_warn("GIC: Adjusting CPU interface base to %pa\n",
                        &cpuif_res.start);
        }
 
index 84b01de..033bccb 100644 (file)
 
 static struct irq_chip jcore_aic;
 
+/*
+ * The J-Core AIC1 and AIC2 are cpu-local interrupt controllers and do
+ * not distinguish or use distinct irq number ranges for per-cpu event
+ * interrupts (timer, IPI). Since information to determine whether a
+ * particular irq number should be treated as per-cpu is not available
+ * at mapping time, we use a wrapper handler function which chooses
+ * the right handler at runtime based on whether IRQF_PERCPU was used
+ * when requesting the irq.
+ */
+
+static void handle_jcore_irq(struct irq_desc *desc)
+{
+       if (irqd_is_per_cpu(irq_desc_get_irq_data(desc)))
+               handle_percpu_irq(desc);
+       else
+               handle_simple_irq(desc);
+}
+
 static int jcore_aic_irqdomain_map(struct irq_domain *d, unsigned int irq,
                                   irq_hw_number_t hwirq)
 {
        struct irq_chip *aic = d->host_data;
 
-       irq_set_chip_and_handler(irq, aic, handle_simple_irq);
+       irq_set_chip_and_handler(irq, aic, handle_jcore_irq);
 
        return 0;
 }
index 8abde6b..6d53810 100644 (file)
@@ -266,7 +266,7 @@ static struct raid_type {
        {"raid10_offset", "raid10 offset (striped mirrors)",        0, 2, 10, ALGORITHM_RAID10_OFFSET},
        {"raid10_near",   "raid10 near (striped mirrors)",          0, 2, 10, ALGORITHM_RAID10_NEAR},
        {"raid10",        "raid10 (striped mirrors)",               0, 2, 10, ALGORITHM_RAID10_DEFAULT},
-       {"raid4",         "raid4 (dedicated last parity disk)",     1, 2, 4,  ALGORITHM_PARITY_N}, /* raid4 layout = raid5_n */
+       {"raid4",         "raid4 (dedicated first parity disk)",    1, 2, 5,  ALGORITHM_PARITY_0}, /* raid4 layout = raid5_0 */
        {"raid5_n",       "raid5 (dedicated last parity disk)",     1, 2, 5,  ALGORITHM_PARITY_N},
        {"raid5_ls",      "raid5 (left symmetric)",                 1, 2, 5,  ALGORITHM_LEFT_SYMMETRIC},
        {"raid5_rs",      "raid5 (right symmetric)",                1, 2, 5,  ALGORITHM_RIGHT_SYMMETRIC},
@@ -2087,11 +2087,11 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev)
                /*
                 * No takeover/reshaping, because we don't have the extended v1.9.0 metadata
                 */
-               if (le32_to_cpu(sb->level) != mddev->level) {
+               if (le32_to_cpu(sb->level) != mddev->new_level) {
                        DMERR("Reshaping/takeover raid sets not yet supported. (raid level/stripes/size change)");
                        return -EINVAL;
                }
-               if (le32_to_cpu(sb->layout) != mddev->layout) {
+               if (le32_to_cpu(sb->layout) != mddev->new_layout) {
                        DMERR("Reshaping raid sets not yet supported. (raid layout change)");
                        DMERR("  0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout);
                        DMERR("  Old layout: %s w/ %d copies",
@@ -2102,7 +2102,7 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev)
                              raid10_md_layout_to_copies(mddev->layout));
                        return -EINVAL;
                }
-               if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) {
+               if (le32_to_cpu(sb->stripe_sectors) != mddev->new_chunk_sectors) {
                        DMERR("Reshaping raid sets not yet supported. (stripe sectors change)");
                        return -EINVAL;
                }
@@ -2115,6 +2115,8 @@ static int super_init_validation(struct raid_set *rs, struct md_rdev *rdev)
                        return -EINVAL;
                }
 
+               DMINFO("Discovered old metadata format; upgrading to extended metadata format");
+
                /* Table line is checked vs. authoritative superblock */
                rs_set_new(rs);
        }
@@ -2258,7 +2260,8 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
        if (!mddev->events && super_init_validation(rs, rdev))
                return -EINVAL;
 
-       if (le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) {
+       if (le32_to_cpu(sb->compat_features) &&
+           le32_to_cpu(sb->compat_features) != FEATURE_FLAG_SUPPORTS_V190) {
                rs->ti->error = "Unable to assemble array: Unknown flag(s) in compatible feature flags";
                return -EINVAL;
        }
@@ -3646,7 +3649,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 9, 0},
+       .version = {1, 9, 1},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index bdf1606..9a8b710 100644 (file)
@@ -145,7 +145,6 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
 
 struct dm_raid1_bio_record {
        struct mirror *m;
-       /* if details->bi_bdev == NULL, details were not saved */
        struct dm_bio_details details;
        region_t write_region;
 };
@@ -1200,8 +1199,6 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
        struct dm_raid1_bio_record *bio_record =
          dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
 
-       bio_record->details.bi_bdev = NULL;
-
        if (rw == WRITE) {
                /* Save region for mirror_end_io() handler */
                bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
@@ -1260,22 +1257,12 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
        }
 
        if (error == -EOPNOTSUPP)
-               goto out;
+               return error;
 
        if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
-               goto out;
+               return error;
 
        if (unlikely(error)) {
-               if (!bio_record->details.bi_bdev) {
-                       /*
-                        * There wasn't enough memory to record necessary
-                        * information for a retry or there was no other
-                        * mirror in-sync.
-                        */
-                       DMERR_LIMIT("Mirror read failed.");
-                       return -EIO;
-               }
-
                m = bio_record->m;
 
                DMERR("Mirror read failed from %s. Trying alternative device.",
@@ -1291,7 +1278,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
                        bd = &bio_record->details;
 
                        dm_bio_restore(bd, bio);
-                       bio_record->details.bi_bdev = NULL;
+                       bio->bi_error = 0;
 
                        queue_bio(ms, bio, rw);
                        return DM_ENDIO_INCOMPLETE;
@@ -1299,9 +1286,6 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
                DMERR("All replicated volumes dead, failing I/O");
        }
 
-out:
-       bio_record->details.bi_bdev = NULL;
-
        return error;
 }
 
index dc75bea..1d0d2ad 100644 (file)
@@ -856,8 +856,11 @@ int dm_old_init_request_queue(struct mapped_device *md)
        kthread_init_worker(&md->kworker);
        md->kworker_task = kthread_run(kthread_worker_fn, &md->kworker,
                                       "kdmwork-%s", dm_device_name(md));
-       if (IS_ERR(md->kworker_task))
-               return PTR_ERR(md->kworker_task);
+       if (IS_ERR(md->kworker_task)) {
+               int error = PTR_ERR(md->kworker_task);
+               md->kworker_task = NULL;
+               return error;
+       }
 
        elv_register_queue(md->queue);
 
index 3e407a9..c4b53b3 100644 (file)
@@ -695,37 +695,32 @@ int dm_table_add_target(struct dm_table *t, const char *type,
 
        tgt->type = dm_get_target_type(type);
        if (!tgt->type) {
-               DMERR("%s: %s: unknown target type", dm_device_name(t->md),
-                     type);
+               DMERR("%s: %s: unknown target type", dm_device_name(t->md), type);
                return -EINVAL;
        }
 
        if (dm_target_needs_singleton(tgt->type)) {
                if (t->num_targets) {
-                       DMERR("%s: target type %s must appear alone in table",
-                             dm_device_name(t->md), type);
-                       return -EINVAL;
+                       tgt->error = "singleton target type must appear alone in table";
+                       goto bad;
                }
                t->singleton = true;
        }
 
        if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
-               DMERR("%s: target type %s may not be included in read-only tables",
-                     dm_device_name(t->md), type);
-               return -EINVAL;
+               tgt->error = "target type may not be included in a read-only table";
+               goto bad;
        }
 
        if (t->immutable_target_type) {
                if (t->immutable_target_type != tgt->type) {
-                       DMERR("%s: immutable target type %s cannot be mixed with other target types",
-                             dm_device_name(t->md), t->immutable_target_type->name);
-                       return -EINVAL;
+                       tgt->error = "immutable target type cannot be mixed with other target types";
+                       goto bad;
                }
        } else if (dm_target_is_immutable(tgt->type)) {
                if (t->num_targets) {
-                       DMERR("%s: immutable target type %s cannot be mixed with other target types",
-                             dm_device_name(t->md), tgt->type->name);
-                       return -EINVAL;
+                       tgt->error = "immutable target type cannot be mixed with other target types";
+                       goto bad;
                }
                t->immutable_target_type = tgt->type;
        }
@@ -740,7 +735,6 @@ int dm_table_add_target(struct dm_table *t, const char *type,
         */
        if (!adjoin(t, tgt)) {
                tgt->error = "Gap in table";
-               r = -EINVAL;
                goto bad;
        }
 
index 147af95..ef7bf1d 100644 (file)
@@ -1423,8 +1423,6 @@ static void cleanup_mapped_device(struct mapped_device *md)
        if (md->bs)
                bioset_free(md->bs);
 
-       cleanup_srcu_struct(&md->io_barrier);
-
        if (md->disk) {
                spin_lock(&_minor_lock);
                md->disk->private_data = NULL;
@@ -1436,6 +1434,8 @@ static void cleanup_mapped_device(struct mapped_device *md)
        if (md->queue)
                blk_cleanup_queue(md->queue);
 
+       cleanup_srcu_struct(&md->io_barrier);
+
        if (md->bdev) {
                bdput(md->bdev);
                md->bdev = NULL;
index 4769469..2c9232e 100644 (file)
@@ -124,8 +124,8 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
        }
 
        /* Get user pages for DMA Xfer */
-       err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count, 0,
-                       1, dma->map);
+       err = get_user_pages_unlocked(user_dma.uaddr, user_dma.page_count,
+                       dma->map, FOLL_FORCE);
 
        if (user_dma.page_count != err) {
                IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
index b094054..f7299d3 100644 (file)
@@ -76,11 +76,12 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
 
        /* Get user pages for DMA Xfer */
        y_pages = get_user_pages_unlocked(y_dma.uaddr,
-                       y_dma.page_count, 0, 1, &dma->map[0]);
+                       y_dma.page_count, &dma->map[0], FOLL_FORCE);
        uv_pages = 0; /* silence gcc. value is set and consumed only if: */
        if (y_pages == y_dma.page_count) {
                uv_pages = get_user_pages_unlocked(uv_dma.uaddr,
-                               uv_dma.page_count, 0, 1, &dma->map[y_pages]);
+                               uv_dma.page_count, &dma->map[y_pages],
+                               FOLL_FORCE);
        }
 
        if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
index e668dde..a31b95c 100644 (file)
@@ -214,7 +214,7 @@ static int omap_vout_get_userptr(struct videobuf_buffer *vb, u32 virtp,
        if (!vec)
                return -ENOMEM;
 
-       ret = get_vaddr_frames(virtp, 1, true, false, vec);
+       ret = get_vaddr_frames(virtp, 1, FOLL_WRITE, vec);
        if (ret != 1) {
                frame_vector_destroy(vec);
                return -EINVAL;
index f300f06..1db0af6 100644 (file)
@@ -156,6 +156,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 {
        unsigned long first, last;
        int err, rw = 0;
+       unsigned int flags = FOLL_FORCE;
 
        dma->direction = direction;
        switch (dma->direction) {
@@ -178,12 +179,14 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
        if (NULL == dma->pages)
                return -ENOMEM;
 
+       if (rw == READ)
+               flags |= FOLL_WRITE;
+
        dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n",
                data, size, dma->nr_pages);
 
        err = get_user_pages(data & PAGE_MASK, dma->nr_pages,
-                            rw == READ, 1, /* force */
-                            dma->pages, NULL);
+                            flags, dma->pages, NULL);
 
        if (err != dma->nr_pages) {
                dma->nr_pages = (err >= 0) ? err : 0;
index 3c3b517..1cd322e 100644 (file)
@@ -42,6 +42,10 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
        unsigned long first, last;
        unsigned long nr;
        struct frame_vector *vec;
+       unsigned int flags = FOLL_FORCE;
+
+       if (write)
+               flags |= FOLL_WRITE;
 
        first = start >> PAGE_SHIFT;
        last = (start + length - 1) >> PAGE_SHIFT;
@@ -49,7 +53,7 @@ struct frame_vector *vb2_create_framevec(unsigned long start,
        vec = frame_vector_create(nr);
        if (!vec)
                return ERR_PTR(-ENOMEM);
-       ret = get_vaddr_frames(start & PAGE_MASK, nr, write, true, vec);
+       ret = get_vaddr_frames(start & PAGE_MASK, nr, flags, vec);
        if (ret < 0)
                goto out_destroy;
        /* We accept only complete set of PFNs */
index d34bc35..2e3cf01 100644 (file)
@@ -524,6 +524,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work)
        int rc;
 
        if (!host->req) {
+               pm_runtime_get_sync(ms_dev(host));
                do {
                        rc = memstick_next_req(msh, &host->req);
                        dev_dbg(ms_dev(host), "next req %d\n", rc);
@@ -544,6 +545,7 @@ static void rtsx_usb_ms_handle_req(struct work_struct *work)
                                                host->req->error);
                        }
                } while (!rc);
+               pm_runtime_put(ms_dev(host));
        }
 
 }
@@ -570,6 +572,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh,
        dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
                        __func__, param, value);
 
+       pm_runtime_get_sync(ms_dev(host));
        mutex_lock(&ucr->dev_mutex);
 
        err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD);
@@ -635,6 +638,7 @@ static int rtsx_usb_ms_set_param(struct memstick_host *msh,
        }
 out:
        mutex_unlock(&ucr->dev_mutex);
+       pm_runtime_put(ms_dev(host));
 
        /* power-on delay */
        if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON)
@@ -681,6 +685,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
        int err;
 
        for (;;) {
+               pm_runtime_get_sync(ms_dev(host));
                mutex_lock(&ucr->dev_mutex);
 
                /* Check pending MS card changes */
@@ -703,6 +708,7 @@ static int rtsx_usb_detect_ms_card(void *__host)
                }
 
 poll_again:
+               pm_runtime_put(ms_dev(host));
                if (host->eject)
                        break;
 
index f3d34b9..2e5233b 100644 (file)
@@ -229,6 +229,14 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
        if (ctx->status == STARTED)
                goto out; /* already started */
 
+       /*
+        * Increment the mapped context count for adapter. This also checks
+        * if adapter_context_lock is taken.
+        */
+       rc = cxl_adapter_context_get(ctx->afu->adapter);
+       if (rc)
+               goto out;
+
        if (task) {
                ctx->pid = get_task_pid(task, PIDTYPE_PID);
                ctx->glpid = get_task_pid(task->group_leader, PIDTYPE_PID);
@@ -239,7 +247,10 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
        cxl_ctx_get();
 
        if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
+               put_pid(ctx->glpid);
                put_pid(ctx->pid);
+               ctx->glpid = ctx->pid = NULL;
+               cxl_adapter_context_put(ctx->afu->adapter);
                cxl_ctx_put();
                goto out;
        }
index c466ee2..5e506c1 100644 (file)
@@ -238,6 +238,9 @@ int __detach_context(struct cxl_context *ctx)
        put_pid(ctx->glpid);
 
        cxl_ctx_put();
+
+       /* Decrease the attached context count on the adapter */
+       cxl_adapter_context_put(ctx->afu->adapter);
        return 0;
 }
 
index 01d372a..a144073 100644 (file)
@@ -618,6 +618,14 @@ struct cxl {
        bool perst_select_user;
        bool perst_same_image;
        bool psl_timebase_synced;
+
+       /*
+        * number of contexts mapped on to this card. Possible values are:
+        * >0: Number of contexts mapped and new one can be mapped.
+        *  0: No active contexts and new ones can be mapped.
+        * -1: No contexts mapped and new ones cannot be mapped.
+        */
+       atomic_t contexts_num;
 };
 
 int cxl_pci_alloc_one_irq(struct cxl *adapter);
@@ -944,4 +952,20 @@ bool cxl_pci_is_vphb_device(struct pci_dev *dev);
 
 /* decode AFU error bits in the PSL register PSL_SERR_An */
 void cxl_afu_decode_psl_serr(struct cxl_afu *afu, u64 serr);
+
+/*
+ * Increments the number of attached contexts on an adapter.
+ * In case an adapter_context_lock is taken the return -EBUSY.
+ */
+int cxl_adapter_context_get(struct cxl *adapter);
+
+/* Decrements the number of attached contexts on an adapter */
+void cxl_adapter_context_put(struct cxl *adapter);
+
+/* If no active contexts then prevents contexts from being attached */
+int cxl_adapter_context_lock(struct cxl *adapter);
+
+/* Unlock the contexts-lock if taken. Warn and force unlock otherwise */
+void cxl_adapter_context_unlock(struct cxl *adapter);
+
 #endif
index 5fb9894..77080cc 100644 (file)
@@ -193,6 +193,16 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
 
        ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF);
 
+       /*
+        * Increment the mapped context count for adapter. This also checks
+        * if adapter_context_lock is taken.
+        */
+       rc = cxl_adapter_context_get(ctx->afu->adapter);
+       if (rc) {
+               afu_release_irqs(ctx, ctx);
+               goto out;
+       }
+
        /*
         * We grab the PID here and not in the file open to allow for the case
         * where a process (master, some daemon, etc) has opened the chardev on
@@ -205,11 +215,16 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
        ctx->pid = get_task_pid(current, PIDTYPE_PID);
        ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID);
 
+
        trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
 
        if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
                                                        amr))) {
                afu_release_irqs(ctx, ctx);
+               cxl_adapter_context_put(ctx->afu->adapter);
+               put_pid(ctx->glpid);
+               put_pid(ctx->pid);
+               ctx->glpid = ctx->pid = NULL;
                goto out;
        }
 
index 9aa58a7..3e102cd 100644 (file)
@@ -1152,6 +1152,9 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic
        if ((rc = cxl_sysfs_adapter_add(adapter)))
                goto err_put1;
 
+       /* release the context lock as the adapter is configured */
+       cxl_adapter_context_unlock(adapter);
+
        return adapter;
 
 err_put1:
index d9be23b..62e0dfb 100644 (file)
@@ -243,8 +243,10 @@ struct cxl *cxl_alloc_adapter(void)
        if (dev_set_name(&adapter->dev, "card%i", adapter->adapter_num))
                goto err2;
 
-       return adapter;
+       /* start with context lock taken */
+       atomic_set(&adapter->contexts_num, -1);
 
+       return adapter;
 err2:
        cxl_remove_adapter_nr(adapter);
 err1:
@@ -286,6 +288,44 @@ int cxl_afu_select_best_mode(struct cxl_afu *afu)
        return 0;
 }
 
+int cxl_adapter_context_get(struct cxl *adapter)
+{
+       int rc;
+
+       rc = atomic_inc_unless_negative(&adapter->contexts_num);
+       return rc >= 0 ? 0 : -EBUSY;
+}
+
+void cxl_adapter_context_put(struct cxl *adapter)
+{
+       atomic_dec_if_positive(&adapter->contexts_num);
+}
+
+int cxl_adapter_context_lock(struct cxl *adapter)
+{
+       int rc;
+       /* no active contexts -> contexts_num == 0 */
+       rc = atomic_cmpxchg(&adapter->contexts_num, 0, -1);
+       return rc ? -EBUSY : 0;
+}
+
+void cxl_adapter_context_unlock(struct cxl *adapter)
+{
+       int val = atomic_cmpxchg(&adapter->contexts_num, -1, 0);
+
+       /*
+        * contexts lock taken -> contexts_num == -1
+        * If not true then show a warning and force reset the lock.
+        * This will happen when context_unlock was requested without
+        * doing a context_lock.
+        */
+       if (val != -1) {
+               atomic_set(&adapter->contexts_num, 0);
+               WARN(1, "Adapter context unlocked with %d active contexts",
+                    val);
+       }
+}
+
 static int __init init_cxl(void)
 {
        int rc = 0;
index 7afad84..e96be9c 100644 (file)
@@ -1487,6 +1487,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
        if ((rc = cxl_native_register_psl_err_irq(adapter)))
                goto err;
 
+       /* Release the context lock as adapter is configured */
+       cxl_adapter_context_unlock(adapter);
        return 0;
 
 err:
index b043c20..a8b6d6a 100644 (file)
@@ -75,12 +75,31 @@ static ssize_t reset_adapter_store(struct device *device,
        int val;
 
        rc = sscanf(buf, "%i", &val);
-       if ((rc != 1) || (val != 1))
+       if ((rc != 1) || (val != 1 && val != -1))
                return -EINVAL;
 
-       if ((rc = cxl_ops->adapter_reset(adapter)))
-               return rc;
-       return count;
+       /*
+        * See if we can lock the context mapping that's only allowed
+        * when there are no contexts attached to the adapter. Once
+        * taken this will also prevent any context from getting activated.
+        */
+       if (val == 1) {
+               rc =  cxl_adapter_context_lock(adapter);
+               if (rc)
+                       goto out;
+
+               rc = cxl_ops->adapter_reset(adapter);
+               /* In case reset failed release context lock */
+               if (rc)
+                       cxl_adapter_context_unlock(adapter);
+
+       } else if (val == -1) {
+               /* Perform a forced adapter reset */
+               rc = cxl_ops->adapter_reset(adapter);
+       }
+
+out:
+       return rc ? rc : count;
 }
 
 static ssize_t load_image_on_perst_show(struct device *device,
index 8a679ec..fc2794b 100644 (file)
@@ -352,17 +352,27 @@ int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl,
                if (copy_from_user(sgl->lpage, user_addr + user_size -
                                   sgl->lpage_size, sgl->lpage_size)) {
                        rc = -EFAULT;
-                       goto err_out1;
+                       goto err_out2;
                }
        }
        return 0;
 
+ err_out2:
+       __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage,
+                                sgl->lpage_dma_addr);
+       sgl->lpage = NULL;
+       sgl->lpage_dma_addr = 0;
  err_out1:
        __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage,
                                 sgl->fpage_dma_addr);
+       sgl->fpage = NULL;
+       sgl->fpage_dma_addr = 0;
  err_out:
        __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl,
                                 sgl->sgl_dma_addr);
+       sgl->sgl = NULL;
+       sgl->sgl_dma_addr = 0;
+       sgl->sgl_size = 0;
        return -ENOMEM;
 }
 
index e6e5e55..60415a2 100644 (file)
@@ -981,11 +981,13 @@ static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack)
        hisr = mei_txe_br_reg_read(hw, HISR_REG);
 
        aliveness = mei_txe_aliveness_get(dev);
-       if (hhisr & IPC_HHIER_SEC && aliveness)
+       if (hhisr & IPC_HHIER_SEC && aliveness) {
                ipc_isr = mei_txe_sec_reg_read_silent(hw,
                                SEC_IPC_HOST_INT_STATUS_REG);
-       else
+       } else {
                ipc_isr = 0;
+               hhisr &= ~IPC_HHIER_SEC;
+       }
 
        generated = generated ||
                (hisr & HISR_INT_STS_MSK) ||
index e0203b1..f806a44 100644 (file)
@@ -1396,8 +1396,7 @@ retry:
                pinned_pages->nr_pages = get_user_pages(
                                (u64)addr,
                                nr_pages,
-                               !!(prot & SCIF_PROT_WRITE),
-                               0,
+                               (prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
                                pinned_pages->pages,
                                NULL);
                up_write(&mm->mmap_sem);
index a2d97b9..6fb773d 100644 (file)
@@ -198,7 +198,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
 #else
        *pageshift = PAGE_SHIFT;
 #endif
-       if (get_user_pages(vaddr, 1, write, 0, &page, NULL) <= 0)
+       if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0)
                return -EFAULT;
        *paddr = page_to_phys(page);
        put_page(page);
index 1525870..33741ad 100644 (file)
@@ -283,7 +283,7 @@ static void gru_unload_mm_tracker(struct gru_state *gru,
        spin_lock(&gru->gs_asid_lock);
        BUG_ON((asids->mt_ctxbitmap & ctxbitmap) != ctxbitmap);
        asids->mt_ctxbitmap ^= ctxbitmap;
-       gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum 0x%d, asidmap 0x%lx\n",
+       gru_dbg(grudev, "gid %d, gts %p, gms %p, ctxnum %d, asidmap 0x%lx\n",
                gru->gs_gid, gts, gms, gts->ts_ctxnum, gms->ms_asidmap[0]);
        spin_unlock(&gru->gs_asid_lock);
        spin_unlock(&gms->ms_asid_lock);
index a8cee33..b3fa738 100644 (file)
@@ -431,6 +431,12 @@ int vmci_doorbell_create(struct vmci_handle *handle,
        if (vmci_handle_is_invalid(*handle)) {
                u32 context_id = vmci_get_context_id();
 
+               if (context_id == VMCI_INVALID_ID) {
+                       pr_warn("Failed to get context ID\n");
+                       result = VMCI_ERROR_NO_RESOURCES;
+                       goto free_mem;
+               }
+
                /* Let resource code allocate a free ID for us */
                new_handle = vmci_make_handle(context_id, VMCI_INVALID_ID);
        } else {
@@ -525,7 +531,7 @@ int vmci_doorbell_destroy(struct vmci_handle handle)
 
        entry = container_of(resource, struct dbell_entry, resource);
 
-       if (vmci_guest_code_active()) {
+       if (!hlist_unhashed(&entry->node)) {
                int result;
 
                dbell_index_table_remove(entry);
index 896be15..d7eaf1e 100644 (file)
@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
-MODULE_VERSION("1.1.4.0-k");
+MODULE_VERSION("1.1.5.0-k");
 MODULE_LICENSE("GPL v2");
index c333511..709a872 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/uaccess.h>
 
 #include "queue.h"
+#include "block.h"
 
 MODULE_ALIAS("mmc:block");
 #ifdef MODULE_PARAM_PREFIX
@@ -1786,7 +1787,7 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
        struct mmc_blk_data *md = mq->data;
        struct mmc_packed *packed = mqrq->packed;
        bool do_rel_wr, do_data_tag;
-       u32 *packed_cmd_hdr;
+       __le32 *packed_cmd_hdr;
        u8 hdr_blocks;
        u8 i = 1;
 
index 3c15a75..342f1e3 100644 (file)
@@ -31,7 +31,7 @@ enum mmc_packed_type {
 
 struct mmc_packed {
        struct list_head        list;
-       u32                     cmd_hdr[1024];
+       __le32                  cmd_hdr[1024];
        unsigned int            blocks;
        u8                      nr_entries;
        u8                      retries;
index 3486bc7..39fc5b2 100644 (file)
@@ -1263,6 +1263,16 @@ static int mmc_select_hs400es(struct mmc_card *card)
                goto out_err;
        }
 
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_2V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
+
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
+
+       /* If fails try again during next card power cycle */
+       if (err)
+               goto out_err;
+
        err = mmc_select_bus_width(card);
        if (err < 0)
                goto out_err;
@@ -1272,6 +1282,8 @@ static int mmc_select_hs400es(struct mmc_card *card)
        if (err)
                goto out_err;
 
+       mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+
        err = mmc_switch_status(card);
        if (err)
                goto out_err;
index 4106295..6e9c0f8 100644 (file)
@@ -1138,11 +1138,6 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        dev_dbg(sdmmc_dev(host), "%s\n", __func__);
        mutex_lock(&ucr->dev_mutex);
 
-       if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) {
-               mutex_unlock(&ucr->dev_mutex);
-               return;
-       }
-
        sd_set_power_mode(host, ios->power_mode);
        sd_set_bus_width(host, ios->bus_width);
        sd_set_timing(host, ios->timing, &host->ddr_mode);
@@ -1314,6 +1309,7 @@ static void rtsx_usb_update_led(struct work_struct *work)
                container_of(work, struct rtsx_usb_sdmmc, led_work);
        struct rtsx_ucr *ucr = host->ucr;
 
+       pm_runtime_get_sync(sdmmc_dev(host));
        mutex_lock(&ucr->dev_mutex);
 
        if (host->led.brightness == LED_OFF)
@@ -1322,6 +1318,7 @@ static void rtsx_usb_update_led(struct work_struct *work)
                rtsx_usb_turn_on_led(ucr);
 
        mutex_unlock(&ucr->dev_mutex);
+       pm_runtime_put(sdmmc_dev(host));
 }
 #endif
 
index 1f54fd8..7123ef9 100644 (file)
@@ -346,7 +346,8 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
        struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
        u32 data;
 
-       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
+       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE ||
+                       reg == SDHCI_INT_STATUS)) {
                if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) {
                        /*
                         * Clear and then set D3CD bit to avoid missing the
@@ -555,6 +556,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
        esdhc_clrset_le(host, 0xffff, val, reg);
 }
 
+static u8 esdhc_readb_le(struct sdhci_host *host, int reg)
+{
+       u8 ret;
+       u32 val;
+
+       switch (reg) {
+       case SDHCI_HOST_CONTROL:
+               val = readl(host->ioaddr + reg);
+
+               ret = val & SDHCI_CTRL_LED;
+               ret |= (val >> 5) & SDHCI_CTRL_DMA_MASK;
+               ret |= (val & ESDHC_CTRL_4BITBUS);
+               ret |= (val & ESDHC_CTRL_8BITBUS) << 3;
+               return ret;
+       }
+
+       return readb(host->ioaddr + reg);
+}
+
 static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -947,6 +967,7 @@ static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl_le,
        .read_w = esdhc_readw_le,
+       .read_b = esdhc_readb_le,
        .write_l = esdhc_writel_le,
        .write_w = esdhc_writew_le,
        .write_b = esdhc_writeb_le,
index da8e40a..410a55b 100644 (file)
@@ -250,7 +250,7 @@ static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
        writel(vendor, host->ioaddr + SDHCI_ARASAN_VENDOR_REGISTER);
 }
 
-void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
+static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
 {
        u8 ctrl;
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -265,6 +265,28 @@ void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
        }
 }
 
+static int sdhci_arasan_voltage_switch(struct mmc_host *mmc,
+                                      struct mmc_ios *ios)
+{
+       switch (ios->signal_voltage) {
+       case MMC_SIGNAL_VOLTAGE_180:
+               /*
+                * Plese don't switch to 1V8 as arasan,5.1 doesn't
+                * actually refer to this setting to indicate the
+                * signal voltage and the state machine will be broken
+                * actually if we force to enable 1V8. That's something
+                * like broken quirk but we could work around here.
+                */
+               return 0;
+       case MMC_SIGNAL_VOLTAGE_330:
+       case MMC_SIGNAL_VOLTAGE_120:
+               /* We don't support 3V3 and 1V2 */
+               break;
+       }
+
+       return -EINVAL;
+}
+
 static struct sdhci_ops sdhci_arasan_ops = {
        .set_clock = sdhci_arasan_set_clock,
        .get_max_clock = sdhci_pltfm_clk_get_max_clock,
@@ -661,6 +683,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
 
                host->mmc_host_ops.hs400_enhanced_strobe =
                                        sdhci_arasan_hs400_enhanced_strobe;
+               host->mmc_host_ops.start_signal_voltage_switch =
+                                       sdhci_arasan_voltage_switch;
        }
 
        ret = sdhci_add_host(host);
index 72a1f1f..1d9e00a 100644 (file)
 #include "sdhci-pci.h"
 #include "sdhci-pci-o2micro.h"
 
+static int sdhci_pci_enable_dma(struct sdhci_host *host);
+static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width);
+static void sdhci_pci_hw_reset(struct sdhci_host *host);
+static int sdhci_pci_select_drive_strength(struct sdhci_host *host,
+                                          struct mmc_card *card,
+                                          unsigned int max_dtr, int host_drv,
+                                          int card_drv, int *drv_type);
+
 /*****************************************************************************\
  *                                                                           *
  * Hardware specific quirk handling                                          *
@@ -390,6 +398,45 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
        return 0;
 }
 
+#define SDHCI_INTEL_PWR_TIMEOUT_CNT    20
+#define SDHCI_INTEL_PWR_TIMEOUT_UDELAY 100
+
+static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
+                                 unsigned short vdd)
+{
+       int cntr;
+       u8 reg;
+
+       sdhci_set_power(host, mode, vdd);
+
+       if (mode == MMC_POWER_OFF)
+               return;
+
+       /*
+        * Bus power might not enable after D3 -> D0 transition due to the
+        * present state not yet having propagated. Retry for up to 2ms.
+        */
+       for (cntr = 0; cntr < SDHCI_INTEL_PWR_TIMEOUT_CNT; cntr++) {
+               reg = sdhci_readb(host, SDHCI_POWER_CONTROL);
+               if (reg & SDHCI_POWER_ON)
+                       break;
+               udelay(SDHCI_INTEL_PWR_TIMEOUT_UDELAY);
+               reg |= SDHCI_POWER_ON;
+               sdhci_writeb(host, reg, SDHCI_POWER_CONTROL);
+       }
+}
+
+static const struct sdhci_ops sdhci_intel_byt_ops = {
+       .set_clock              = sdhci_set_clock,
+       .set_power              = sdhci_intel_set_power,
+       .enable_dma             = sdhci_pci_enable_dma,
+       .set_bus_width          = sdhci_pci_set_bus_width,
+       .reset                  = sdhci_reset,
+       .set_uhs_signaling      = sdhci_set_uhs_signaling,
+       .hw_reset               = sdhci_pci_hw_reset,
+       .select_drive_strength  = sdhci_pci_select_drive_strength,
+};
+
 static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
        .allow_runtime_pm = true,
        .probe_slot     = byt_emmc_probe_slot,
@@ -397,6 +444,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
        .quirks2        = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
                          SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 |
                          SDHCI_QUIRK2_STOP_WITH_TC,
+       .ops            = &sdhci_intel_byt_ops,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
@@ -405,6 +453,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
                        SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
        .allow_runtime_pm = true,
        .probe_slot     = byt_sdio_probe_slot,
+       .ops            = &sdhci_intel_byt_ops,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
@@ -415,6 +464,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
        .allow_runtime_pm = true,
        .own_cd_for_runtime_pm = true,
        .probe_slot     = byt_sd_probe_slot,
+       .ops            = &sdhci_intel_byt_ops,
 };
 
 /* Define Host controllers for Intel Merrifield platform */
@@ -1648,7 +1698,9 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
        }
 
        host->hw_name = "PCI";
-       host->ops = &sdhci_pci_ops;
+       host->ops = chip->fixes && chip->fixes->ops ?
+                   chip->fixes->ops :
+                   &sdhci_pci_ops;
        host->quirks = chip->quirks;
        host->quirks2 = chip->quirks2;
 
index 9c7c08b..6bccf56 100644 (file)
@@ -65,6 +65,8 @@ struct sdhci_pci_fixes {
 
        int                     (*suspend) (struct sdhci_pci_chip *);
        int                     (*resume) (struct sdhci_pci_chip *);
+
+       const struct sdhci_ops  *ops;
 };
 
 struct sdhci_pci_slot {
index dd1938d..d0f5c05 100644 (file)
@@ -315,7 +315,7 @@ static void pxav3_set_power(struct sdhci_host *host, unsigned char mode,
        struct mmc_host *mmc = host->mmc;
        u8 pwr = host->pwr;
 
-       sdhci_set_power(host, mode, vdd);
+       sdhci_set_power_noreg(host, mode, vdd);
 
        if (host->pwr == pwr)
                return;
index 4805566..71654b9 100644 (file)
@@ -687,7 +687,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
                         * host->clock is in Hz.  target_timeout is in us.
                         * Hence, us = 1000000 * cycles / Hz.  Round up.
                         */
-                       val = 1000000 * data->timeout_clks;
+                       val = 1000000ULL * data->timeout_clks;
                        if (do_div(val, host->clock))
                                target_timeout++;
                        target_timeout += val;
@@ -1077,6 +1077,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
        /* Initially, a command has no error */
        cmd->error = 0;
 
+       if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
+           cmd->opcode == MMC_STOP_TRANSMISSION)
+               cmd->flags |= MMC_RSP_BUSY;
+
        /* Wait max 10 ms */
        timeout = 10;
 
@@ -1390,8 +1394,8 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
                sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
 }
 
-void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
-                    unsigned short vdd)
+void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
+                          unsigned short vdd)
 {
        u8 pwr = 0;
 
@@ -1455,20 +1459,17 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
                        mdelay(10);
        }
 }
-EXPORT_SYMBOL_GPL(sdhci_set_power);
+EXPORT_SYMBOL_GPL(sdhci_set_power_noreg);
 
-static void __sdhci_set_power(struct sdhci_host *host, unsigned char mode,
-                             unsigned short vdd)
+void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
+                    unsigned short vdd)
 {
-       struct mmc_host *mmc = host->mmc;
-
-       if (host->ops->set_power)
-               host->ops->set_power(host, mode, vdd);
-       else if (!IS_ERR(mmc->supply.vmmc))
-               sdhci_set_power_reg(host, mode, vdd);
+       if (IS_ERR(host->mmc->supply.vmmc))
+               sdhci_set_power_noreg(host, mode, vdd);
        else
-               sdhci_set_power(host, mode, vdd);
+               sdhci_set_power_reg(host, mode, vdd);
 }
+EXPORT_SYMBOL_GPL(sdhci_set_power);
 
 /*****************************************************************************\
  *                                                                           *
@@ -1609,7 +1610,10 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                }
        }
 
-       __sdhci_set_power(host, ios->power_mode, ios->vdd);
+       if (host->ops->set_power)
+               host->ops->set_power(host, ios->power_mode, ios->vdd);
+       else
+               sdhci_set_power(host, ios->power_mode, ios->vdd);
 
        if (host->ops->platform_send_init_74_clocks)
                host->ops->platform_send_init_74_clocks(host, ios->power_mode);
@@ -2409,7 +2413,7 @@ static void sdhci_timeout_data_timer(unsigned long data)
  *                                                                           *
 \*****************************************************************************/
 
-static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
+static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
 {
        if (!host->cmd) {
                /*
@@ -2453,11 +2457,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
                return;
        }
 
-       if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) &&
-           !(host->cmd->flags & MMC_RSP_BUSY) && !host->data &&
-           host->cmd->opcode == MMC_STOP_TRANSMISSION)
-               *mask &= ~SDHCI_INT_DATA_END;
-
        if (intmask & SDHCI_INT_RESPONSE)
                sdhci_finish_command(host);
 }
@@ -2680,8 +2679,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                }
 
                if (intmask & SDHCI_INT_CMD_MASK)
-                       sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK,
-                                     &intmask);
+                       sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
 
                if (intmask & SDHCI_INT_DATA_MASK)
                        sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
index c722cd2..766df17 100644 (file)
@@ -683,6 +683,8 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
 void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
 void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
                     unsigned short vdd);
+void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
+                          unsigned short vdd);
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
 void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
index 95c4048..388e46b 100644 (file)
@@ -741,6 +741,7 @@ static int try_recover_peb(struct ubi_volume *vol, int pnum, int lnum,
                goto out_put;
        }
 
+       vid_hdr = ubi_get_vid_hdr(vidb);
        ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
 
        mutex_lock(&ubi->buf_mutex);
index d6384d9..c1f5c29 100644 (file)
@@ -287,7 +287,7 @@ static int update_vol(struct ubi_device *ubi, struct ubi_attach_info *ai,
 
                /* new_aeb is newer */
                if (cmp_res & 1) {
-                       victim = ubi_alloc_aeb(ai, aeb->ec, aeb->pnum);
+                       victim = ubi_alloc_aeb(ai, aeb->pnum, aeb->ec);
                        if (!victim)
                                return -ENOMEM;
 
@@ -707,11 +707,11 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
                             fmvhdr->vol_type,
                             be32_to_cpu(fmvhdr->last_eb_bytes));
 
-               if (!av)
-                       goto fail_bad;
-               if (PTR_ERR(av) == -EINVAL) {
-                       ubi_err(ubi, "volume (ID %i) already exists",
-                               fmvhdr->vol_id);
+               if (IS_ERR(av)) {
+                       if (PTR_ERR(av) == -EEXIST)
+                               ubi_err(ubi, "volume (ID %i) already exists",
+                                       fmvhdr->vol_id);
+
                        goto fail_bad;
                }
 
index 76fb855..ef63d24 100644 (file)
@@ -256,6 +256,7 @@ static const struct of_device_id b53_mmap_of_table[] = {
        { .compatible = "brcm,bcm63xx-switch" },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, b53_mmap_of_table);
 
 static struct platform_driver b53_mmap_driver = {
        .probe = b53_mmap_probe,
index e218887..e3ee27c 100644 (file)
@@ -1133,6 +1133,20 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
+{
+       struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);
+
+       /* For a kernel about to be kexec'd we want to keep the GPHY on for a
+        * successful MDIO bus scan to occur. If we did turn off the GPHY
+        * before (e.g: port_disable), this will also power it back on.
+        *
+        * Do not rely on kexec_in_progress, just power the PHY on.
+        */
+       if (priv->hw_params.num_gphy == 1)
+               bcm_sf2_gphy_enable_set(priv->dev->ds, true);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int bcm_sf2_suspend(struct device *dev)
 {
@@ -1158,10 +1172,12 @@ static const struct of_device_id bcm_sf2_of_match[] = {
        { .compatible = "brcm,bcm7445-switch-v4.0" },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, bcm_sf2_of_match);
 
 static struct platform_driver bcm_sf2_driver = {
        .probe  = bcm_sf2_sw_probe,
        .remove = bcm_sf2_sw_remove,
+       .shutdown = bcm_sf2_sw_shutdown,
        .driver = {
                .name = "brcm-sf2",
                .of_match_table = bcm_sf2_of_match,
index b047fd6..00c38bf 100644 (file)
@@ -1358,6 +1358,7 @@ static const struct of_device_id nb8800_dt_ids[] = {
        },
        { }
 };
+MODULE_DEVICE_TABLE(of, nb8800_dt_ids);
 
 static int nb8800_probe(struct platform_device *pdev)
 {
index ae364c7..5370909 100644 (file)
@@ -1126,7 +1126,8 @@ out_freeirq:
        free_irq(dev->irq, dev);
 
 out_phy_disconnect:
-       phy_disconnect(phydev);
+       if (priv->has_phy)
+               phy_disconnect(phydev);
 
        return ret;
 }
index 856379c..31ca204 100644 (file)
@@ -1449,7 +1449,7 @@ static int bgmac_phy_connect(struct bgmac *bgmac)
        phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
                              PHY_INTERFACE_MODE_MII);
        if (IS_ERR(phy_dev)) {
-               dev_err(bgmac->dev, "PHY connecton failed\n");
+               dev_err(bgmac->dev, "PHY connection failed\n");
                return PTR_ERR(phy_dev);
        }
 
index 27f11a5..b3791b3 100644 (file)
@@ -271,22 +271,25 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
 static u32
 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
 {
+       unsigned long flags;
        u32 val;
 
-       spin_lock_bh(&bp->indirect_lock);
+       spin_lock_irqsave(&bp->indirect_lock, flags);
        BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
        val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW);
-       spin_unlock_bh(&bp->indirect_lock);
+       spin_unlock_irqrestore(&bp->indirect_lock, flags);
        return val;
 }
 
 static void
 bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
 {
-       spin_lock_bh(&bp->indirect_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bp->indirect_lock, flags);
        BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
        BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
-       spin_unlock_bh(&bp->indirect_lock);
+       spin_unlock_irqrestore(&bp->indirect_lock, flags);
 }
 
 static void
@@ -304,8 +307,10 @@ bnx2_shmem_rd(struct bnx2 *bp, u32 offset)
 static void
 bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
 {
+       unsigned long flags;
+
        offset += cid_addr;
-       spin_lock_bh(&bp->indirect_lock);
+       spin_lock_irqsave(&bp->indirect_lock, flags);
        if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                int i;
 
@@ -322,7 +327,7 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
                BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset);
                BNX2_WR(bp, BNX2_CTX_DATA, val);
        }
-       spin_unlock_bh(&bp->indirect_lock);
+       spin_unlock_irqrestore(&bp->indirect_lock, flags);
 }
 
 #ifdef BCM_CNIC
index 20fe6a8..0cee4c0 100644 (file)
@@ -15241,7 +15241,7 @@ static void bnx2x_init_cyclecounter(struct bnx2x *bp)
        memset(&bp->cyclecounter, 0, sizeof(bp->cyclecounter));
        bp->cyclecounter.read = bnx2x_cyclecounter_read;
        bp->cyclecounter.mask = CYCLECOUNTER_MASK(64);
-       bp->cyclecounter.shift = 1;
+       bp->cyclecounter.shift = 0;
        bp->cyclecounter.mult = 1;
 }
 
index f320497..57eb4e1 100644 (file)
@@ -4057,7 +4057,7 @@ static void cfg_queues(struct adapter *adap)
                 * capped by the number of available cores.
                 */
                if (n10g) {
-                       i = num_online_cpus();
+                       i = min_t(int, MAX_OFLD_QSETS, num_online_cpus());
                        s->ofldqsets = roundup(i, adap->params.nports);
                } else {
                        s->ofldqsets = adap->params.nports;
index 0945fa4..2471ff4 100644 (file)
@@ -135,15 +135,17 @@ static int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
 }
 
 static int alloc_uld_rxqs(struct adapter *adap,
-                         struct sge_uld_rxq_info *rxq_info,
-                         unsigned int nq, unsigned int offset, bool lro)
+                         struct sge_uld_rxq_info *rxq_info, bool lro)
 {
        struct sge *s = &adap->sge;
-       struct sge_ofld_rxq *q = rxq_info->uldrxq + offset;
-       unsigned short *ids = rxq_info->rspq_id + offset;
-       unsigned int per_chan = nq / adap->params.nports;
+       unsigned int nq = rxq_info->nrxq + rxq_info->nciq;
+       struct sge_ofld_rxq *q = rxq_info->uldrxq;
+       unsigned short *ids = rxq_info->rspq_id;
        unsigned int bmap_idx = 0;
-       int i, err, msi_idx;
+       unsigned int per_chan;
+       int i, err, msi_idx, que_idx = 0;
+
+       per_chan = rxq_info->nrxq / adap->params.nports;
 
        if (adap->flags & USING_MSIX)
                msi_idx = 1;
@@ -151,12 +153,18 @@ static int alloc_uld_rxqs(struct adapter *adap,
                msi_idx = -((int)s->intrq.abs_id + 1);
 
        for (i = 0; i < nq; i++, q++) {
+               if (i == rxq_info->nrxq) {
+                       /* start allocation of concentrator queues */
+                       per_chan = rxq_info->nciq / adap->params.nports;
+                       que_idx = 0;
+               }
+
                if (msi_idx >= 0) {
                        bmap_idx = get_msix_idx_from_bmap(adap);
                        msi_idx = adap->msix_info_ulds[bmap_idx].idx;
                }
                err = t4_sge_alloc_rxq(adap, &q->rspq, false,
-                                      adap->port[i / per_chan],
+                                      adap->port[que_idx++ / per_chan],
                                       msi_idx,
                                       q->fl.size ? &q->fl : NULL,
                                       uldrx_handler,
@@ -165,29 +173,19 @@ static int alloc_uld_rxqs(struct adapter *adap,
                if (err)
                        goto freeout;
                if (msi_idx >= 0)
-                       rxq_info->msix_tbl[i + offset] = bmap_idx;
+                       rxq_info->msix_tbl[i] = bmap_idx;
                memset(&q->stats, 0, sizeof(q->stats));
                if (ids)
                        ids[i] = q->rspq.abs_id;
        }
        return 0;
 freeout:
-       q = rxq_info->uldrxq + offset;
+       q = rxq_info->uldrxq;
        for ( ; i; i--, q++) {
                if (q->rspq.desc)
                        free_rspq_fl(adap, &q->rspq,
                                     q->fl.size ? &q->fl : NULL);
        }
-
-       /* We need to free rxq also in case of ciq allocation failure */
-       if (offset) {
-               q = rxq_info->uldrxq + offset;
-               for ( ; i; i--, q++) {
-                       if (q->rspq.desc)
-                               free_rspq_fl(adap, &q->rspq,
-                                            q->fl.size ? &q->fl : NULL);
-               }
-       }
        return err;
 }
 
@@ -205,9 +203,7 @@ setup_sge_queues_uld(struct adapter *adap, unsigned int uld_type, bool lro)
                        return -ENOMEM;
        }
 
-       ret = !(!alloc_uld_rxqs(adap, rxq_info, rxq_info->nrxq, 0, lro) &&
-                !alloc_uld_rxqs(adap, rxq_info, rxq_info->nciq,
-                                rxq_info->nrxq, lro));
+       ret = !(!alloc_uld_rxqs(adap, rxq_info, lro));
 
        /* Tell uP to route control queue completions to rdma rspq */
        if (adap->flags & FULL_INIT_DONE &&
index 539de76..cbd68a8 100644 (file)
@@ -210,8 +210,10 @@ static int t4_sched_queue_bind(struct port_info *pi, struct ch_sched_queue *p)
 
        /* Unbind queue from any existing class */
        err = t4_sched_queue_unbind(pi, p);
-       if (err)
+       if (err) {
+               t4_free_mem(qe);
                goto out;
+       }
 
        /* Bind queue to specified class */
        memset(qe, 0, sizeof(*qe));
index e572a52..36bc2c7 100644 (file)
@@ -169,19 +169,28 @@ int vnic_rq_disable(struct vnic_rq *rq)
 {
        unsigned int wait;
        struct vnic_dev *vdev = rq->vdev;
+       int i;
 
-       iowrite32(0, &rq->ctrl->enable);
+       /* Due to a race condition with clearing RQ "mini-cache" in hw, we need
+        * to disable the RQ twice to guarantee that stale descriptors are not
+        * used when this RQ is re-enabled.
+        */
+       for (i = 0; i < 2; i++) {
+               iowrite32(0, &rq->ctrl->enable);
 
-       /* Wait for HW to ACK disable request */
-       for (wait = 0; wait < 1000; wait++) {
-               if (!(ioread32(&rq->ctrl->running)))
-                       return 0;
-               udelay(10);
-       }
+               /* Wait for HW to ACK disable request */
+               for (wait = 20000; wait > 0; wait--)
+                       if (!ioread32(&rq->ctrl->running))
+                               break;
+               if (!wait) {
+                       vdev_neterr(vdev, "Failed to disable RQ[%d]\n",
+                                   rq->index);
 
-       vdev_neterr(vdev, "Failed to disable RQ[%d]\n", rq->index);
+                       return -ETIMEDOUT;
+               }
+       }
 
-       return -ETIMEDOUT;
+       return 0;
 }
 
 void vnic_rq_clean(struct vnic_rq *rq,
@@ -212,6 +221,11 @@ void vnic_rq_clean(struct vnic_rq *rq,
                        [fetch_index % VNIC_RQ_BUF_BLK_ENTRIES(count)];
        iowrite32(fetch_index, &rq->ctrl->posted_index);
 
+       /* Anytime we write fetch_index, we need to re-write 0 to rq->enable
+        * to re-sync internal VIC state.
+        */
+       iowrite32(0, &rq->ctrl->enable);
+
        vnic_dev_clear_desc_ring(&rq->ring);
 }
 
index f928e6f..223f35c 100644 (file)
@@ -669,6 +669,7 @@ static const struct of_device_id nps_enet_dt_ids[] = {
        { .compatible = "ezchip,nps-mgt-enet" },
        { /* Sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, nps_enet_dt_ids);
 
 static struct platform_driver nps_enet_driver = {
        .probe = nps_enet_probe,
index 48a033e..5aa9d4d 100644 (file)
@@ -1430,14 +1430,14 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
                skb_put(skb, pkt_len - 4);
                data = skb->data;
 
+               if (!is_copybreak && need_swap)
+                       swap_buffer(data, pkt_len);
+
 #if !defined(CONFIG_M5272)
                if (fep->quirks & FEC_QUIRK_HAS_RACC)
                        data = skb_pull_inline(skb, 2);
 #endif
 
-               if (!is_copybreak && need_swap)
-                       swap_buffer(data, pkt_len);
-
                /* Extract the enhanced buffer descriptor */
                ebdp = NULL;
                if (fep->bufdesc_ex)
index 8d70377..8ea3d95 100644 (file)
@@ -2751,6 +2751,7 @@ static const struct of_device_id g_dsaf_match[] = {
        {.compatible = "hisilicon,hns-dsaf-v2"},
        {}
 };
+MODULE_DEVICE_TABLE(of, g_dsaf_match);
 
 static struct platform_driver g_dsaf_driver = {
        .probe = hns_dsaf_probe,
index 33f4c48..501eb20 100644 (file)
@@ -563,6 +563,7 @@ static const struct of_device_id hns_mdio_match[] = {
        {.compatible = "hisilicon,hns-mdio"},
        {}
 };
+MODULE_DEVICE_TABLE(of, hns_mdio_match);
 
 static const struct acpi_device_id hns_mdio_acpi_match[] = {
        { "HISI0141", 0 },
index bfe17d9..5f44c55 100644 (file)
@@ -1190,7 +1190,7 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
        if (!scrq)
                return NULL;
 
-       scrq->msgs = (union sub_crq *)__get_free_pages(GFP_KERNEL, 2);
+       scrq->msgs = (union sub_crq *)__get_free_pages(GFP_ATOMIC, 2);
        memset(scrq->msgs, 0, 4 * PAGE_SIZE);
        if (!scrq->msgs) {
                dev_warn(dev, "Couldn't allocate crq queue messages page\n");
@@ -1461,14 +1461,16 @@ static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter)
        return rc;
 
 req_rx_irq_failed:
-       for (j = 0; j < i; j++)
+       for (j = 0; j < i; j++) {
                free_irq(adapter->rx_scrq[j]->irq, adapter->rx_scrq[j]);
                irq_dispose_mapping(adapter->rx_scrq[j]->irq);
+       }
        i = adapter->req_tx_queues;
 req_tx_irq_failed:
-       for (j = 0; j < i; j++)
+       for (j = 0; j < i; j++) {
                free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]);
                irq_dispose_mapping(adapter->rx_scrq[j]->irq);
+       }
        release_sub_crqs_no_irqs(adapter);
        return rc;
 }
@@ -3232,6 +3234,27 @@ static void ibmvnic_free_inflight(struct ibmvnic_adapter *adapter)
        spin_unlock_irqrestore(&adapter->inflight_lock, flags);
 }
 
+static void ibmvnic_xport_event(struct work_struct *work)
+{
+       struct ibmvnic_adapter *adapter = container_of(work,
+                                                      struct ibmvnic_adapter,
+                                                      ibmvnic_xport);
+       struct device *dev = &adapter->vdev->dev;
+       long rc;
+
+       ibmvnic_free_inflight(adapter);
+       release_sub_crqs(adapter);
+       if (adapter->migrated) {
+               rc = ibmvnic_reenable_crq_queue(adapter);
+               if (rc)
+                       dev_err(dev, "Error after enable rc=%ld\n", rc);
+               adapter->migrated = false;
+               rc = ibmvnic_send_crq_init(adapter);
+               if (rc)
+                       dev_err(dev, "Error sending init rc=%ld\n", rc);
+       }
+}
+
 static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                               struct ibmvnic_adapter *adapter)
 {
@@ -3267,15 +3290,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
                        dev_info(dev, "Re-enabling adapter\n");
                        adapter->migrated = true;
-                       ibmvnic_free_inflight(adapter);
-                       release_sub_crqs(adapter);
-                       rc = ibmvnic_reenable_crq_queue(adapter);
-                       if (rc)
-                               dev_err(dev, "Error after enable rc=%ld\n", rc);
-                       adapter->migrated = false;
-                       rc = ibmvnic_send_crq_init(adapter);
-                       if (rc)
-                               dev_err(dev, "Error sending init rc=%ld\n", rc);
+                       schedule_work(&adapter->ibmvnic_xport);
                } else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) {
                        dev_info(dev, "Backing device failover detected\n");
                        netif_carrier_off(netdev);
@@ -3284,8 +3299,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                        /* The adapter lost the connection */
                        dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
                                gen_crq->cmd);
-                       ibmvnic_free_inflight(adapter);
-                       release_sub_crqs(adapter);
+                       schedule_work(&adapter->ibmvnic_xport);
                }
                return;
        case IBMVNIC_CRQ_CMD_RSP:
@@ -3654,6 +3668,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;
 
        if (adapter->failover) {
                adapter->failover = false;
@@ -3725,6 +3740,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
        SET_NETDEV_DEV(netdev, &dev->dev);
 
        INIT_WORK(&adapter->vnic_crq_init, handle_crq_init_rsp);
+       INIT_WORK(&adapter->ibmvnic_xport, ibmvnic_xport_event);
 
        spin_lock_init(&adapter->stats_lock);
 
@@ -3792,6 +3808,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;
 
        rc = register_netdev(netdev);
        if (rc) {
index bfc84c7..dd775d9 100644 (file)
@@ -27,7 +27,7 @@
 /**************************************************************************/
 
 #define IBMVNIC_NAME           "ibmvnic"
-#define IBMVNIC_DRIVER_VERSION "1.0"
+#define IBMVNIC_DRIVER_VERSION "1.0.1"
 #define IBMVNIC_INVALID_MAP    -1
 #define IBMVNIC_STATS_TIMEOUT  1
 /* basic structures plus 100 2k buffers */
@@ -1048,5 +1048,6 @@ struct ibmvnic_adapter {
        u8 map_id;
 
        struct work_struct vnic_crq_init;
+       struct work_struct ibmvnic_xport;
        bool failover;
 };
index 2030d7c..6d61e44 100644 (file)
@@ -92,6 +92,7 @@
 #define I40E_AQ_LEN                    256
 #define I40E_AQ_WORK_LIMIT             66 /* max number of VFs + a little */
 #define I40E_MAX_USER_PRIORITY         8
+#define I40E_DEFAULT_TRAFFIC_CLASS     BIT(0)
 #define I40E_DEFAULT_MSG_ENABLE                4
 #define I40E_QUEUE_WAIT_RETRY_LIMIT    10
 #define I40E_INT_NAME_STR_LEN          (IFNAMSIZ + 16)
index ac1faee..31c97e3 100644 (file)
@@ -4640,29 +4640,6 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)
        return num_tc;
 }
 
-/**
- * i40e_pf_get_default_tc - Get bitmap for first enabled TC
- * @pf: PF being queried
- *
- * Return a bitmap for first enabled traffic class for this PF.
- **/
-static u8 i40e_pf_get_default_tc(struct i40e_pf *pf)
-{
-       u8 enabled_tc = pf->hw.func_caps.enabled_tcmap;
-       u8 i = 0;
-
-       if (!enabled_tc)
-               return 0x1; /* TC0 */
-
-       /* Find the first enabled TC */
-       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
-               if (enabled_tc & BIT(i))
-                       break;
-       }
-
-       return BIT(i);
-}
-
 /**
  * i40e_pf_get_pf_tc_map - Get bitmap for enabled traffic classes
  * @pf: PF being queried
@@ -4673,7 +4650,7 @@ static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
 {
        /* If DCB is not enabled for this PF then just return default TC */
        if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
-               return i40e_pf_get_default_tc(pf);
+               return I40E_DEFAULT_TRAFFIC_CLASS;
 
        /* SFP mode we want PF to be enabled for all TCs */
        if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
@@ -4683,7 +4660,7 @@ static u8 i40e_pf_get_tc_map(struct i40e_pf *pf)
        if (pf->hw.func_caps.iscsi)
                return i40e_get_iscsi_tc_map(pf);
        else
-               return i40e_pf_get_default_tc(pf);
+               return I40E_DEFAULT_TRAFFIC_CLASS;
 }
 
 /**
@@ -5029,7 +5006,7 @@ static void i40e_dcb_reconfigure(struct i40e_pf *pf)
                if (v == pf->lan_vsi)
                        tc_map = i40e_pf_get_tc_map(pf);
                else
-                       tc_map = i40e_pf_get_default_tc(pf);
+                       tc_map = I40E_DEFAULT_TRAFFIC_CLASS;
 #ifdef I40E_FCOE
                if (pf->vsi[v]->type == I40E_VSI_FCOE)
                        tc_map = i40e_get_fcoe_tc_map(pf);
@@ -5717,7 +5694,7 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf,
        u8 type;
 
        /* Not DCB capable or capability disabled */
-       if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
+       if (!(pf->flags & I40E_FLAG_DCB_CAPABLE))
                return ret;
 
        /* Ignore if event is not for Nearest Bridge */
@@ -7707,6 +7684,7 @@ static int i40e_init_msix(struct i40e_pf *pf)
                pf->flags &= ~I40E_FLAG_MSIX_ENABLED;
                kfree(pf->msix_entries);
                pf->msix_entries = NULL;
+               pci_disable_msix(pf->pdev);
                return -ENODEV;
 
        } else if (v_actual == I40E_MIN_MSIX) {
@@ -9056,7 +9034,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                return 0;
 
        return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
-                                      nlflags, 0, 0, filter_mask, NULL);
+                                      0, 0, nlflags, filter_mask, NULL);
 }
 
 /* Hardware supports L4 tunnel length of 128B (=2^7) which includes
index a244d9a..bd93d82 100644 (file)
@@ -9135,10 +9135,14 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
                goto fwd_add_err;
        fwd_adapter->pool = pool;
        fwd_adapter->real_adapter = adapter;
-       err = ixgbe_fwd_ring_up(vdev, fwd_adapter);
-       if (err)
-               goto fwd_add_err;
-       netif_tx_start_all_queues(vdev);
+
+       if (netif_running(pdev)) {
+               err = ixgbe_fwd_ring_up(vdev, fwd_adapter);
+               if (err)
+                       goto fwd_add_err;
+               netif_tx_start_all_queues(vdev);
+       }
+
        return fwd_adapter;
 fwd_add_err:
        /* unwind counter and free adapter struct */
index 5583118..bf5cc55 100644 (file)
@@ -2968,6 +2968,22 @@ static void set_params(struct mv643xx_eth_private *mp,
        mp->txq_count = pd->tx_queue_count ? : 1;
 }
 
+static int get_phy_mode(struct mv643xx_eth_private *mp)
+{
+       struct device *dev = mp->dev->dev.parent;
+       int iface = -1;
+
+       if (dev->of_node)
+               iface = of_get_phy_mode(dev->of_node);
+
+       /* Historical default if unspecified. We could also read/write
+        * the interface state in the PSC1
+        */
+       if (iface < 0)
+               iface = PHY_INTERFACE_MODE_GMII;
+       return iface;
+}
+
 static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
                                   int phy_addr)
 {
@@ -2994,7 +3010,7 @@ static struct phy_device *phy_scan(struct mv643xx_eth_private *mp,
                                "orion-mdio-mii", addr);
 
                phydev = phy_connect(mp->dev, phy_id, mv643xx_eth_adjust_link,
-                               PHY_INTERFACE_MODE_GMII);
+                                    get_phy_mode(mp));
                if (!IS_ERR(phydev)) {
                        phy_addr_set(mp, addr);
                        break;
@@ -3090,6 +3106,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        if (!dev)
                return -ENOMEM;
 
+       SET_NETDEV_DEV(dev, &pdev->dev);
        mp = netdev_priv(dev);
        platform_set_drvdata(pdev, mp);
 
@@ -3129,7 +3146,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        if (pd->phy_node) {
                mp->phy = of_phy_connect(mp->dev, pd->phy_node,
                                         mv643xx_eth_adjust_link, 0,
-                                        PHY_INTERFACE_MODE_GMII);
+                                        get_phy_mode(mp));
                if (!mp->phy)
                        err = -ENODEV;
                else
@@ -3187,8 +3204,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
        dev->priv_flags |= IFF_UNICAST_FLT;
        dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;
 
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
        if (mp->shared->win_protect)
                wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect);
 
index b1cef7a..e36bebc 100644 (file)
@@ -2469,6 +2469,7 @@ err_comm_admin:
        kfree(priv->mfunc.master.slave_state);
 err_comm:
        iounmap(priv->mfunc.comm);
+       priv->mfunc.comm = NULL;
 err_vhcr:
        dma_free_coherent(&dev->persist->pdev->dev, PAGE_SIZE,
                          priv->mfunc.vhcr,
@@ -2537,6 +2538,13 @@ void mlx4_report_internal_err_comm_event(struct mlx4_dev *dev)
        int slave;
        u32 slave_read;
 
+       /* If the comm channel has not yet been initialized,
+        * skip reporting the internal error event to all
+        * the communication channels.
+        */
+       if (!priv->mfunc.comm)
+               return;
+
        /* Report an internal error event to all
         * communication channels.
         */
@@ -2571,6 +2579,7 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)
        }
 
        iounmap(priv->mfunc.comm);
+       priv->mfunc.comm = NULL;
 }
 
 void mlx4_cmd_cleanup(struct mlx4_dev *dev, int cleanup_mask)
index 08fc5fc..a5fc46b 100644 (file)
@@ -245,8 +245,11 @@ static u32 freq_to_shift(u16 freq)
 {
        u32 freq_khz = freq * 1000;
        u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
+       u64 tmp_rounded =
+               roundup_pow_of_two(max_val_cycles) > max_val_cycles ?
+               roundup_pow_of_two(max_val_cycles) - 1 : UINT_MAX;
        u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ?
-               max_val_cycles : roundup_pow_of_two(max_val_cycles) - 1;
+               max_val_cycles : tmp_rounded;
        /* calculate max possible multiplier in order to fit in 64bit */
        u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded);
 
index 132cea6..e3be7e4 100644 (file)
@@ -127,7 +127,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
                /* For TX we use the same irq per
                ring we assigned for the RX    */
                struct mlx4_en_cq *rx_cq;
-
+               int xdp_index;
+
+               /* The xdp tx irq must align with the rx ring that forwards to
+                * it, so reindex these from 0. This should only happen when
+                * tx_ring_num is not a multiple of rx_ring_num.
+                */
+               xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx;
+               if (xdp_index >= 0)
+                       cq_idx = xdp_index;
                cq_idx = cq_idx % priv->rx_ring_num;
                rx_cq = priv->rx_cq[cq_idx];
                cq->vector = rx_cq->vector;
index 7e703be..12c99a2 100644 (file)
@@ -1733,6 +1733,13 @@ int mlx4_en_start_port(struct net_device *dev)
                udp_tunnel_get_rx_info(dev);
 
        priv->port_up = true;
+
+       /* Process all completions if exist to prevent
+        * the queues freezing if they are full
+        */
+       for (i = 0; i < priv->rx_ring_num; i++)
+               napi_schedule(&priv->rx_cq[i]->napi);
+
        netif_tx_start_all_queues(dev);
        netif_device_attach(dev);
 
@@ -1910,8 +1917,9 @@ static void mlx4_en_clear_stats(struct net_device *dev)
        struct mlx4_en_dev *mdev = priv->mdev;
        int i;
 
-       if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
-               en_dbg(HW, priv, "Failed dumping statistics\n");
+       if (!mlx4_is_slave(mdev->dev))
+               if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
+                       en_dbg(HW, priv, "Failed dumping statistics\n");
 
        memset(&priv->pstats, 0, sizeof(priv->pstats));
        memset(&priv->pkstats, 0, sizeof(priv->pkstats));
@@ -2194,6 +2202,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
 
        if (!shutdown)
                free_netdev(dev);
+       dev->ethtool_ops = NULL;
 }
 
 static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
index 5aa8b75..59473a0 100644 (file)
@@ -166,7 +166,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
                return PTR_ERR(mailbox);
        err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
                           MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B,
-                          MLX4_CMD_WRAPPED);
+                          MLX4_CMD_NATIVE);
        if (err)
                goto out;
 
@@ -322,7 +322,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
                err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma,
                                   in_mod | MLX4_DUMP_ETH_STATS_FLOW_CONTROL,
                                   0, MLX4_CMD_DUMP_ETH_STATS,
-                                  MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
+                                  MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
                if (err)
                        goto out;
        }
index b66e03d..c06346a 100644 (file)
@@ -118,6 +118,29 @@ mlx4_en_test_loopback_exit:
        return !loopback_ok;
 }
 
+static int mlx4_en_test_interrupts(struct mlx4_en_priv *priv)
+{
+       struct mlx4_en_dev *mdev = priv->mdev;
+       int err = 0;
+       int i = 0;
+
+       err = mlx4_test_async(mdev->dev);
+       /* When not in MSI_X or slave, test only async */
+       if (!(mdev->dev->flags & MLX4_FLAG_MSI_X) || mlx4_is_slave(mdev->dev))
+               return err;
+
+       /* A loop over all completion vectors of current port,
+        * for each vector check whether it works by mapping command
+        * completions to that vector and performing a NOP command
+        */
+       for (i = 0; i < priv->rx_ring_num; i++) {
+               err = mlx4_test_interrupt(mdev->dev, priv->rx_cq[i]->vector);
+               if (err)
+                       break;
+       }
+
+       return err;
+}
 
 static int mlx4_en_test_link(struct mlx4_en_priv *priv)
 {
@@ -151,7 +174,6 @@ static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
 void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-       struct mlx4_en_dev *mdev = priv->mdev;
        int i, carrier_ok;
 
        memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
@@ -177,7 +199,7 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
                        netif_carrier_on(dev);
 
        }
-       buf[0] = mlx4_test_interrupts(mdev->dev);
+       buf[0] = mlx4_en_test_interrupts(priv);
        buf[1] = mlx4_en_test_link(priv);
        buf[2] = mlx4_en_test_speed(priv);
 
index cf8f8a7..cd3638e 100644 (file)
@@ -1361,53 +1361,49 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        kfree(priv->eq_table.uar_map);
 }
 
-/* A test that verifies that we can accept interrupts on all
- * the irq vectors of the device.
+/* A test that verifies that we can accept interrupts
+ * on the vector allocated for asynchronous events
+ */
+int mlx4_test_async(struct mlx4_dev *dev)
+{
+       return mlx4_NOP(dev);
+}
+EXPORT_SYMBOL(mlx4_test_async);
+
+/* A test that verifies that we can accept interrupts
+ * on the given irq vector of the tested port.
  * Interrupts are checked using the NOP command.
  */
-int mlx4_test_interrupts(struct mlx4_dev *dev)
+int mlx4_test_interrupt(struct mlx4_dev *dev, int vector)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
-       int i;
        int err;
 
-       err = mlx4_NOP(dev);
-       /* When not in MSI_X, there is only one irq to check */
-       if (!(dev->flags & MLX4_FLAG_MSI_X) || mlx4_is_slave(dev))
-               return err;
-
-       /* A loop over all completion vectors, for each vector we will check
-        * whether it works by mapping command completions to that vector
-        * and performing a NOP command
-        */
-       for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
-               /* Make sure request_irq was called */
-               if (!priv->eq_table.eq[i].have_irq)
-                       continue;
-
-               /* Temporary use polling for command completions */
-               mlx4_cmd_use_polling(dev);
-
-               /* Map the new eq to handle all asynchronous events */
-               err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
-                                 priv->eq_table.eq[i].eqn);
-               if (err) {
-                       mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
-                       mlx4_cmd_use_events(dev);
-                       break;
-               }
+       /* Temporary use polling for command completions */
+       mlx4_cmd_use_polling(dev);
 
-               /* Go back to using events */
-               mlx4_cmd_use_events(dev);
-               err = mlx4_NOP(dev);
+       /* Map the new eq to handle all asynchronous events */
+       err = mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
+                         priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(vector)].eqn);
+       if (err) {
+               mlx4_warn(dev, "Failed mapping eq for interrupt test\n");
+               goto out;
        }
 
+       /* Go back to using events */
+       mlx4_cmd_use_events(dev);
+       err = mlx4_NOP(dev);
+
        /* Return to default */
+       mlx4_cmd_use_polling(dev);
+out:
        mlx4_MAP_EQ(dev, get_async_ev_mask(dev), 0,
                    priv->eq_table.eq[MLX4_EQ_ASYNC].eqn);
+       mlx4_cmd_use_events(dev);
+
        return err;
 }
-EXPORT_SYMBOL(mlx4_test_interrupts);
+EXPORT_SYMBOL(mlx4_test_interrupt);
 
 bool mlx4_is_eq_vector_valid(struct mlx4_dev *dev, u8 port, int vector)
 {
index c41ab31..84bab9f 100644 (file)
@@ -49,9 +49,9 @@ enum {
 extern void __buggy_use_of_MLX4_GET(void);
 extern void __buggy_use_of_MLX4_PUT(void);
 
-static bool enable_qos = true;
+static bool enable_qos;
 module_param(enable_qos, bool, 0444);
-MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: on)");
+MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: off)");
 
 #define MLX4_GET(dest, source, offset)                               \
        do {                                                          \
index 7183ac4..6f4e67b 100644 (file)
@@ -1102,6 +1102,14 @@ static int __set_port_type(struct mlx4_port_info *info,
        int i;
        int err = 0;
 
+       if ((port_type & mdev->caps.supported_type[info->port]) != port_type) {
+               mlx4_err(mdev,
+                        "Requested port type for port %d is not supported on this HCA\n",
+                        info->port);
+               err = -EINVAL;
+               goto err_sup;
+       }
+
        mlx4_stop_sense(mdev);
        mutex_lock(&priv->port_mutex);
        info->tmp_type = port_type;
@@ -1147,7 +1155,7 @@ static int __set_port_type(struct mlx4_port_info *info,
 out:
        mlx4_start_sense(mdev);
        mutex_unlock(&priv->port_mutex);
-
+err_sup:
        return err;
 }
 
index e4878f3..88ee7d8 100644 (file)
@@ -145,9 +145,10 @@ enum mlx4_resource {
        RES_MTT,
        RES_MAC,
        RES_VLAN,
-       RES_EQ,
+       RES_NPORT_ID,
        RES_COUNTER,
        RES_FS_RULE,
+       RES_EQ,
        MLX4_NUM_OF_RESOURCE_TYPE
 };
 
@@ -1329,8 +1330,6 @@ int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
                               struct mlx4_cmd_info *cmd);
 int mlx4_common_set_vlan_fltr(struct mlx4_dev *dev, int function,
                                     int port, void *buf);
-int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, u32 in_mod,
-                               struct mlx4_cmd_mailbox *outbox);
 int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
                                   struct mlx4_vhcr *vhcr,
                                   struct mlx4_cmd_mailbox *inbox,
index c5b2064..b656dd5 100644 (file)
@@ -1728,24 +1728,13 @@ int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
        return err;
 }
 
-int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave,
-                              u32 in_mod, struct mlx4_cmd_mailbox *outbox)
-{
-       return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0,
-                           MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B,
-                           MLX4_CMD_NATIVE);
-}
-
 int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
                                struct mlx4_vhcr *vhcr,
                                struct mlx4_cmd_mailbox *inbox,
                                struct mlx4_cmd_mailbox *outbox,
                                struct mlx4_cmd_info *cmd)
 {
-       if (slave != dev->caps.function)
-               return 0;
-       return mlx4_common_dump_eth_stats(dev, slave,
-                                         vhcr->in_modifier, outbox);
+       return 0;
 }
 
 int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
index 84d7857..c548bea 100644 (file)
@@ -1605,13 +1605,14 @@ static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index,
                        r->com.from_state = r->com.state;
                        r->com.to_state = state;
                        r->com.state = RES_EQ_BUSY;
-                       if (eq)
-                               *eq = r;
                }
        }
 
        spin_unlock_irq(mlx4_tlock(dev));
 
+       if (!err && eq)
+               *eq = r;
+
        return err;
 }
 
index 6cb3830..2c6e3c7 100644 (file)
 
 #include "mlx5_core.h"
 
+struct mlx5_db_pgdir {
+       struct list_head        list;
+       unsigned long          *bitmap;
+       __be32                 *db_page;
+       dma_addr_t              db_dma;
+};
+
 /* Handling for queue buffers -- we allocate a bunch of memory and
  * register it in a memory region at HCA virtual address 0.
  */
@@ -102,17 +109,28 @@ EXPORT_SYMBOL_GPL(mlx5_buf_free);
 static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
                                                 int node)
 {
+       u32 db_per_page = PAGE_SIZE / cache_line_size();
        struct mlx5_db_pgdir *pgdir;
 
        pgdir = kzalloc(sizeof(*pgdir), GFP_KERNEL);
        if (!pgdir)
                return NULL;
 
-       bitmap_fill(pgdir->bitmap, MLX5_DB_PER_PAGE);
+       pgdir->bitmap = kcalloc(BITS_TO_LONGS(db_per_page),
+                               sizeof(unsigned long),
+                               GFP_KERNEL);
+
+       if (!pgdir->bitmap) {
+               kfree(pgdir);
+               return NULL;
+       }
+
+       bitmap_fill(pgdir->bitmap, db_per_page);
 
        pgdir->db_page = mlx5_dma_zalloc_coherent_node(dev, PAGE_SIZE,
                                                       &pgdir->db_dma, node);
        if (!pgdir->db_page) {
+               kfree(pgdir->bitmap);
                kfree(pgdir);
                return NULL;
        }
@@ -123,18 +141,19 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
 static int mlx5_alloc_db_from_pgdir(struct mlx5_db_pgdir *pgdir,
                                    struct mlx5_db *db)
 {
+       u32 db_per_page = PAGE_SIZE / cache_line_size();
        int offset;
        int i;
 
-       i = find_first_bit(pgdir->bitmap, MLX5_DB_PER_PAGE);
-       if (i >= MLX5_DB_PER_PAGE)
+       i = find_first_bit(pgdir->bitmap, db_per_page);
+       if (i >= db_per_page)
                return -ENOMEM;
 
        __clear_bit(i, pgdir->bitmap);
 
        db->u.pgdir = pgdir;
        db->index   = i;
-       offset = db->index * L1_CACHE_BYTES;
+       offset = db->index * cache_line_size();
        db->db      = pgdir->db_page + offset / sizeof(*pgdir->db_page);
        db->dma     = pgdir->db_dma  + offset;
 
@@ -181,14 +200,16 @@ EXPORT_SYMBOL_GPL(mlx5_db_alloc);
 
 void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db)
 {
+       u32 db_per_page = PAGE_SIZE / cache_line_size();
        mutex_lock(&dev->priv.pgdir_mutex);
 
        __set_bit(db->index, db->u.pgdir->bitmap);
 
-       if (bitmap_full(db->u.pgdir->bitmap, MLX5_DB_PER_PAGE)) {
+       if (bitmap_full(db->u.pgdir->bitmap, db_per_page)) {
                dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE,
                                  db->u.pgdir->db_page, db->u.pgdir->db_dma);
                list_del(&db->u.pgdir->list);
+               kfree(db->u.pgdir->bitmap);
                kfree(db->u.pgdir);
        }
 
index 460363b..7a43502 100644 (file)
@@ -85,6 +85,9 @@
 #define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD      (128)
 
 #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ                 (64 * 1024)
+#define MLX5E_DEFAULT_LRO_TIMEOUT                       32
+#define MLX5E_LRO_TIMEOUT_ARR_SIZE                      4
+
 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC      0x10
 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC_FROM_CQE 0x3
 #define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS      0x20
@@ -221,6 +224,7 @@ struct mlx5e_params {
        struct ieee_ets ets;
 #endif
        bool rx_am_enabled;
+       u32 lro_timeout;
 };
 
 struct mlx5e_tstamp {
@@ -888,5 +892,6 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
 void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
 struct rtnl_link_stats64 *
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
+u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout);
 
 #endif /* __MLX5_EN_H__ */
index 7eaf380..f4c687c 100644 (file)
@@ -1971,9 +1971,7 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
        MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
                 (priv->params.lro_wqe_sz -
                  ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
-       MLX5_SET(tirc, tirc, lro_timeout_period_usecs,
-                MLX5_CAP_ETH(priv->mdev,
-                             lro_timer_supported_periods[2]));
+       MLX5_SET(tirc, tirc, lro_timeout_period_usecs, priv->params.lro_timeout);
 }
 
 void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
@@ -3401,6 +3399,18 @@ static void mlx5e_query_min_inline(struct mlx5_core_dev *mdev,
        }
 }
 
+u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout)
+{
+       int i;
+
+       /* The supported periods are organized in ascending order */
+       for (i = 0; i < MLX5E_LRO_TIMEOUT_ARR_SIZE - 1; i++)
+               if (MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]) >= wanted_timeout)
+                       break;
+
+       return MLX5_CAP_ETH(mdev, lro_timer_supported_periods[i]);
+}
+
 static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
                                        struct net_device *netdev,
                                        const struct mlx5e_profile *profile,
@@ -3419,6 +3429,9 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
        priv->profile                      = profile;
        priv->ppriv                        = ppriv;
 
+       priv->params.lro_timeout =
+               mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
+
        priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
 
        /* set CQE compression */
@@ -4035,7 +4048,6 @@ void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv)
        const struct mlx5e_profile *profile = priv->profile;
        struct net_device *netdev = priv->netdev;
 
-       unregister_netdev(netdev);
        destroy_workqueue(priv->wq);
        if (profile->cleanup)
                profile->cleanup(priv);
@@ -4052,6 +4064,7 @@ static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
        for (vport = 1; vport < total_vfs; vport++)
                mlx5_eswitch_unregister_vport_rep(esw, vport);
 
+       unregister_netdev(priv->netdev);
        mlx5e_detach(mdev, vpriv);
        mlx5e_destroy_netdev(mdev, priv);
 }
index 3c97da1..7fe6559 100644 (file)
@@ -457,6 +457,7 @@ void mlx5e_vport_rep_unload(struct mlx5_eswitch *esw,
        struct mlx5e_priv *priv = rep->priv_data;
        struct net_device *netdev = priv->netdev;
 
+       unregister_netdev(netdev);
        mlx5e_detach_netdev(esw->dev, netdev);
        mlx5e_destroy_netdev(esw->dev, priv);
 }
index abbf2c3..be1f733 100644 (file)
@@ -931,8 +931,8 @@ static void esw_vport_change_handler(struct work_struct *work)
        mutex_unlock(&esw->state_lock);
 }
 
-static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
-                                       struct mlx5_vport *vport)
+static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
+                                      struct mlx5_vport *vport)
 {
        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
        struct mlx5_flow_group *vlan_grp = NULL;
@@ -949,9 +949,11 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        int table_size = 2;
        int err = 0;
 
-       if (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support) ||
-           !IS_ERR_OR_NULL(vport->egress.acl))
-               return;
+       if (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
+               return -EOPNOTSUPP;
+
+       if (!IS_ERR_OR_NULL(vport->egress.acl))
+               return 0;
 
        esw_debug(dev, "Create vport[%d] egress ACL log_max_size(%d)\n",
                  vport->vport, MLX5_CAP_ESW_EGRESS_ACL(dev, log_max_ft_size));
@@ -959,12 +961,12 @@ static void 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;
+               return -EIO;
        }
 
        flow_group_in = mlx5_vzalloc(inlen);
        if (!flow_group_in)
-               return;
+               return -ENOMEM;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
        if (IS_ERR(acl)) {
@@ -1009,6 +1011,7 @@ out:
                mlx5_destroy_flow_group(vlan_grp);
        if (err && !IS_ERR_OR_NULL(acl))
                mlx5_destroy_flow_table(acl);
+       return err;
 }
 
 static void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
@@ -1041,8 +1044,8 @@ static void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
        vport->egress.acl = NULL;
 }
 
-static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
-                                        struct mlx5_vport *vport)
+static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
+                                       struct mlx5_vport *vport)
 {
        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
        struct mlx5_core_dev *dev = esw->dev;
@@ -1063,9 +1066,11 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        int table_size = 4;
        int err = 0;
 
-       if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support) ||
-           !IS_ERR_OR_NULL(vport->ingress.acl))
-               return;
+       if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
+               return -EOPNOTSUPP;
+
+       if (!IS_ERR_OR_NULL(vport->ingress.acl))
+               return 0;
 
        esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
                  vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
@@ -1073,12 +1078,12 @@ static void 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;
+               return -EIO;
        }
 
        flow_group_in = mlx5_vzalloc(inlen);
        if (!flow_group_in)
-               return;
+               return -ENOMEM;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
        if (IS_ERR(acl)) {
@@ -1167,6 +1172,7 @@ out:
        }
 
        kvfree(flow_group_in);
+       return err;
 }
 
 static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
@@ -1225,7 +1231,13 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
                return 0;
        }
 
-       esw_vport_enable_ingress_acl(esw, vport);
+       err = esw_vport_enable_ingress_acl(esw, vport);
+       if (err) {
+               mlx5_core_warn(esw->dev,
+                              "failed to enable ingress acl (%d) on vport[%d]\n",
+                              err, vport->vport);
+               return err;
+       }
 
        esw_debug(esw->dev,
                  "vport[%d] configure ingress rules, vlan(%d) qos(%d)\n",
@@ -1299,7 +1311,13 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
                return 0;
        }
 
-       esw_vport_enable_egress_acl(esw, vport);
+       err = esw_vport_enable_egress_acl(esw, vport);
+       if (err) {
+               mlx5_core_warn(esw->dev,
+                              "failed to enable egress acl (%d) on vport[%d]\n",
+                              err, vport->vport);
+               return err;
+       }
 
        esw_debug(esw->dev,
                  "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
index 5da2cc8..8969604 100644 (file)
@@ -436,6 +436,9 @@ static void del_flow_group(struct fs_node *node)
        fs_get_obj(ft, fg->node.parent);
        dev = get_dev(&ft->node);
 
+       if (ft->autogroup.active)
+               ft->autogroup.num_groups--;
+
        if (mlx5_cmd_destroy_flow_group(dev, ft, fg->id))
                mlx5_core_warn(dev, "flow steering can't destroy fg %d of ft %d\n",
                               fg->id, ft->id);
@@ -879,7 +882,7 @@ static struct mlx5_flow_group *create_flow_group_common(struct mlx5_flow_table *
        tree_init_node(&fg->node, !is_auto_fg, del_flow_group);
        tree_add_node(&fg->node, &ft->node);
        /* Add node to group list */
-       list_add(&fg->node.list, ft->node.children.prev);
+       list_add(&fg->node.list, prev_fg);
 
        return fg;
 }
@@ -893,7 +896,7 @@ struct mlx5_flow_group *mlx5_create_flow_group(struct mlx5_flow_table *ft,
                return ERR_PTR(-EPERM);
 
        lock_ref_node(&ft->node);
-       fg = create_flow_group_common(ft, fg_in, &ft->node.children, false);
+       fg = create_flow_group_common(ft, fg_in, ft->node.children.prev, false);
        unlock_ref_node(&ft->node);
 
        return fg;
@@ -1012,7 +1015,7 @@ static struct mlx5_flow_group *create_autogroup(struct mlx5_flow_table *ft,
                                                u32 *match_criteria)
 {
        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
-       struct list_head *prev = &ft->node.children;
+       struct list_head *prev = ft->node.children.prev;
        unsigned int candidate_index = 0;
        struct mlx5_flow_group *fg;
        void *match_criteria_addr;
index 3a9195b..3b026c1 100644 (file)
@@ -218,6 +218,7 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging)
                goto err_out;
 
        if (aging) {
+               counter->cache.lastuse = jiffies;
                counter->aging = true;
 
                spin_lock(&fc_stats->addlist_lock);
index 1a05fb9..5bcf934 100644 (file)
@@ -61,10 +61,15 @@ enum {
 enum {
        MLX5_NIC_IFC_FULL               = 0,
        MLX5_NIC_IFC_DISABLED           = 1,
-       MLX5_NIC_IFC_NO_DRAM_NIC        = 2
+       MLX5_NIC_IFC_NO_DRAM_NIC        = 2,
+       MLX5_NIC_IFC_INVALID            = 3
 };
 
-static u8 get_nic_interface(struct mlx5_core_dev *dev)
+enum {
+       MLX5_DROP_NEW_HEALTH_WORK,
+};
+
+static u8 get_nic_state(struct mlx5_core_dev *dev)
 {
        return (ioread32be(&dev->iseg->cmdq_addr_l_sz) >> 8) & 3;
 }
@@ -97,7 +102,7 @@ static int in_fatal(struct mlx5_core_dev *dev)
        struct mlx5_core_health *health = &dev->priv.health;
        struct health_buffer __iomem *h = health->health;
 
-       if (get_nic_interface(dev) == MLX5_NIC_IFC_DISABLED)
+       if (get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
                return 1;
 
        if (ioread32be(&h->fw_ver) == 0xffffffff)
@@ -127,7 +132,7 @@ unlock:
 
 static void mlx5_handle_bad_state(struct mlx5_core_dev *dev)
 {
-       u8 nic_interface = get_nic_interface(dev);
+       u8 nic_interface = get_nic_state(dev);
 
        switch (nic_interface) {
        case MLX5_NIC_IFC_FULL:
@@ -149,8 +154,34 @@ static void mlx5_handle_bad_state(struct mlx5_core_dev *dev)
        mlx5_disable_device(dev);
 }
 
+static void health_recover(struct work_struct *work)
+{
+       struct mlx5_core_health *health;
+       struct delayed_work *dwork;
+       struct mlx5_core_dev *dev;
+       struct mlx5_priv *priv;
+       u8 nic_state;
+
+       dwork = container_of(work, struct delayed_work, work);
+       health = container_of(dwork, struct mlx5_core_health, recover_work);
+       priv = container_of(health, struct mlx5_priv, health);
+       dev = container_of(priv, struct mlx5_core_dev, priv);
+
+       nic_state = get_nic_state(dev);
+       if (nic_state == MLX5_NIC_IFC_INVALID) {
+               dev_err(&dev->pdev->dev, "health recovery flow aborted since the nic state is invalid\n");
+               return;
+       }
+
+       dev_err(&dev->pdev->dev, "starting health recovery flow\n");
+       mlx5_recover_device(dev);
+}
+
+/* How much time to wait until health resetting the driver (in msecs) */
+#define MLX5_RECOVERY_DELAY_MSECS 60000
 static void health_care(struct work_struct *work)
 {
+       unsigned long recover_delay = msecs_to_jiffies(MLX5_RECOVERY_DELAY_MSECS);
        struct mlx5_core_health *health;
        struct mlx5_core_dev *dev;
        struct mlx5_priv *priv;
@@ -160,6 +191,14 @@ static void health_care(struct work_struct *work)
        dev = container_of(priv, struct mlx5_core_dev, priv);
        mlx5_core_warn(dev, "handling bad device here\n");
        mlx5_handle_bad_state(dev);
+
+       spin_lock(&health->wq_lock);
+       if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags))
+               schedule_delayed_work(&health->recover_work, recover_delay);
+       else
+               dev_err(&dev->pdev->dev,
+                       "new health works are not permitted at this stage\n");
+       spin_unlock(&health->wq_lock);
 }
 
 static const char *hsynd_str(u8 synd)
@@ -272,7 +311,13 @@ static void poll_health(unsigned long data)
        if (in_fatal(dev) && !health->sick) {
                health->sick = true;
                print_health_info(dev);
-               schedule_work(&health->work);
+               spin_lock(&health->wq_lock);
+               if (!test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags))
+                       queue_work(health->wq, &health->work);
+               else
+                       dev_err(&dev->pdev->dev,
+                               "new health works are not permitted at this stage\n");
+               spin_unlock(&health->wq_lock);
        }
 }
 
@@ -281,6 +326,8 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev)
        struct mlx5_core_health *health = &dev->priv.health;
 
        init_timer(&health->timer);
+       health->sick = 0;
+       clear_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
        health->health = &dev->iseg->health;
        health->health_counter = &dev->iseg->health_counter;
 
@@ -297,11 +344,22 @@ void mlx5_stop_health_poll(struct mlx5_core_dev *dev)
        del_timer_sync(&health->timer);
 }
 
+void mlx5_drain_health_wq(struct mlx5_core_dev *dev)
+{
+       struct mlx5_core_health *health = &dev->priv.health;
+
+       spin_lock(&health->wq_lock);
+       set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags);
+       spin_unlock(&health->wq_lock);
+       cancel_delayed_work_sync(&health->recover_work);
+       cancel_work_sync(&health->work);
+}
+
 void mlx5_health_cleanup(struct mlx5_core_dev *dev)
 {
        struct mlx5_core_health *health = &dev->priv.health;
 
-       flush_work(&health->work);
+       destroy_workqueue(health->wq);
 }
 
 int mlx5_health_init(struct mlx5_core_dev *dev)
@@ -316,9 +374,13 @@ int mlx5_health_init(struct mlx5_core_dev *dev)
 
        strcpy(name, "mlx5_health");
        strcat(name, dev_name(&dev->pdev->dev));
+       health->wq = create_singlethread_workqueue(name);
        kfree(name);
-
+       if (!health->wq)
+               return -ENOMEM;
+       spin_lock_init(&health->wq_lock);
        INIT_WORK(&health->work, health_care);
+       INIT_DELAYED_WORK(&health->recover_work, health_recover);
 
        return 0;
 }
index d9c3c70..d5433c4 100644 (file)
@@ -844,12 +844,6 @@ static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
        struct pci_dev *pdev = dev->pdev;
        int err;
 
-       err = mlx5_query_hca_caps(dev);
-       if (err) {
-               dev_err(&pdev->dev, "query hca failed\n");
-               goto out;
-       }
-
        err = mlx5_query_board_id(dev);
        if (err) {
                dev_err(&pdev->dev, "query board id failed\n");
@@ -1023,6 +1017,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
 
        mlx5_start_health_poll(dev);
 
+       err = mlx5_query_hca_caps(dev);
+       if (err) {
+               dev_err(&pdev->dev, "query hca failed\n");
+               goto err_stop_poll;
+       }
+
        if (boot && mlx5_init_once(dev, priv)) {
                dev_err(&pdev->dev, "sw objs init failed\n");
                goto err_stop_poll;
@@ -1313,10 +1313,16 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
        struct mlx5_priv *priv = &dev->priv;
 
        dev_info(&pdev->dev, "%s was called\n", __func__);
+
        mlx5_enter_error_state(dev);
        mlx5_unload_one(dev, priv, false);
-       pci_save_state(pdev);
-       mlx5_pci_disable_device(dev);
+       /* In case of kernel call save the pci state and drain health wq */
+       if (state) {
+               pci_save_state(pdev);
+               mlx5_drain_health_wq(dev);
+               mlx5_pci_disable_device(dev);
+       }
+
        return state == pci_channel_io_perm_failure ?
                PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
 }
@@ -1373,11 +1379,6 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev)
        return PCI_ERS_RESULT_RECOVERED;
 }
 
-void mlx5_disable_device(struct mlx5_core_dev *dev)
-{
-       mlx5_pci_err_detected(dev->pdev, 0);
-}
-
 static void mlx5_pci_resume(struct pci_dev *pdev)
 {
        struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
@@ -1427,6 +1428,18 @@ static const struct pci_device_id mlx5_core_pci_table[] = {
 
 MODULE_DEVICE_TABLE(pci, mlx5_core_pci_table);
 
+void mlx5_disable_device(struct mlx5_core_dev *dev)
+{
+       mlx5_pci_err_detected(dev->pdev, 0);
+}
+
+void mlx5_recover_device(struct mlx5_core_dev *dev)
+{
+       mlx5_pci_disable_device(dev);
+       if (mlx5_pci_slot_reset(dev->pdev) == PCI_ERS_RESULT_RECOVERED)
+               mlx5_pci_resume(dev->pdev);
+}
+
 static struct pci_driver mlx5_core_driver = {
        .name           = DRIVER_NAME,
        .id_table       = mlx5_core_pci_table,
index 3d0cfb9..187662c 100644 (file)
@@ -83,6 +83,7 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
                     unsigned long param);
 void mlx5_enter_error_state(struct mlx5_core_dev *dev);
 void mlx5_disable_device(struct mlx5_core_dev *dev);
+void mlx5_recover_device(struct mlx5_core_dev *dev);
 int mlx5_sriov_init(struct mlx5_core_dev *dev);
 void mlx5_sriov_cleanup(struct mlx5_core_dev *dev);
 int mlx5_sriov_attach(struct mlx5_core_dev *dev);
index cc4fd61..a57d5a8 100644 (file)
@@ -209,6 +209,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr)
 static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id)
 {
        struct page *page;
+       u64 zero_addr = 1;
        u64 addr;
        int err;
        int nid = dev_to_node(&dev->pdev->dev);
@@ -218,26 +219,35 @@ static int alloc_system_page(struct mlx5_core_dev *dev, u16 func_id)
                mlx5_core_warn(dev, "failed to allocate page\n");
                return -ENOMEM;
        }
+map:
        addr = dma_map_page(&dev->pdev->dev, page, 0,
                            PAGE_SIZE, DMA_BIDIRECTIONAL);
        if (dma_mapping_error(&dev->pdev->dev, addr)) {
                mlx5_core_warn(dev, "failed dma mapping page\n");
                err = -ENOMEM;
-               goto out_alloc;
+               goto err_mapping;
        }
+
+       /* Firmware doesn't support page with physical address 0 */
+       if (addr == 0) {
+               zero_addr = addr;
+               goto map;
+       }
+
        err = insert_page(dev, addr, page, func_id);
        if (err) {
                mlx5_core_err(dev, "failed to track allocated page\n");
-               goto out_mapping;
+               dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE,
+                              DMA_BIDIRECTIONAL);
        }
 
-       return 0;
-
-out_mapping:
-       dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+err_mapping:
+       if (err)
+               __free_page(page);
 
-out_alloc:
-       __free_page(page);
+       if (zero_addr == 0)
+               dma_unmap_page(&dev->pdev->dev, zero_addr, PAGE_SIZE,
+                              DMA_BIDIRECTIONAL);
 
        return err;
 }
index e742bd4..912f71f 100644 (file)
@@ -1838,11 +1838,17 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
        .cmd_exec               = mlxsw_pci_cmd_exec,
 };
 
-static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci)
+static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
+                             const struct pci_device_id *id)
 {
        unsigned long end;
 
        mlxsw_pci_write32(mlxsw_pci, SW_RESET, MLXSW_PCI_SW_RESET_RST_BIT);
+       if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) {
+               msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
+               return 0;
+       }
+
        wmb(); /* reset needs to be written before we read control register */
        end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
        do {
@@ -1909,7 +1915,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        mlxsw_pci->pdev = pdev;
        pci_set_drvdata(pdev, mlxsw_pci);
 
-       err = mlxsw_pci_sw_reset(mlxsw_pci);
+       err = mlxsw_pci_sw_reset(mlxsw_pci, id);
        if (err) {
                dev_err(&pdev->dev, "Software reset failed\n");
                goto err_sw_reset;
index 78fc557..4573da2 100644 (file)
@@ -320,6 +320,8 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
                                                lpm_tree);
        if (err)
                goto err_left_struct_set;
+       memcpy(&lpm_tree->prefix_usage, prefix_usage,
+              sizeof(lpm_tree->prefix_usage));
        return lpm_tree;
 
 err_left_struct_set:
@@ -343,7 +345,8 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
 
        for (i = 0; i < MLXSW_SP_LPM_TREE_COUNT; i++) {
                lpm_tree = &mlxsw_sp->router.lpm_trees[i];
-               if (lpm_tree->proto == proto &&
+               if (lpm_tree->ref_count != 0 &&
+                   lpm_tree->proto == proto &&
                    mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
                                             prefix_usage))
                        goto inc_ref_count;
@@ -1820,19 +1823,17 @@ err_fib_entry_insert:
        return err;
 }
 
-static int mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
-                                   struct fib_entry_notifier_info *fen_info)
+static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
+                                    struct fib_entry_notifier_info *fen_info)
 {
        struct mlxsw_sp_fib_entry *fib_entry;
 
        if (mlxsw_sp->router.aborted)
-               return 0;
+               return;
 
        fib_entry = mlxsw_sp_fib_entry_find(mlxsw_sp, fen_info);
-       if (!fib_entry) {
-               dev_warn(mlxsw_sp->bus_info->dev, "Failed to find FIB4 entry being removed.\n");
-               return -ENOENT;
-       }
+       if (!fib_entry)
+               return;
 
        if (fib_entry->ref_count == 1) {
                mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
@@ -1840,7 +1841,6 @@ static int mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
        }
 
        mlxsw_sp_fib_entry_put(mlxsw_sp, fib_entry);
-       return 0;
 }
 
 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
@@ -1862,7 +1862,8 @@ static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
        if (err)
                return err;
 
-       mlxsw_reg_raltb_pack(raltb_pl, 0, MLXSW_REG_RALXX_PROTOCOL_IPV4, 0);
+       mlxsw_reg_raltb_pack(raltb_pl, 0, MLXSW_REG_RALXX_PROTOCOL_IPV4,
+                            MLXSW_SP_LPM_TREE_MIN);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
        if (err)
                return err;
index c0c23e2..92bda87 100644 (file)
@@ -1088,6 +1088,7 @@ err_port_stp_state_set:
 err_port_admin_status_set:
 err_port_mtu_set:
 err_port_speed_set:
+       mlxsw_sx_port_swid_set(mlxsw_sx_port, MLXSW_PORT_SWID_DISABLED_PORT);
 err_port_swid_set:
 err_port_system_port_mapping_set:
 port_not_usable:
index 1e8339a..32f2a45 100644 (file)
@@ -107,4 +107,7 @@ config QEDE
        ---help---
          This enables the support for ...
 
+config QED_RDMA
+       bool
+
 endif # NET_VENDOR_QLOGIC
index cda0af7..967acf3 100644 (file)
@@ -5,4 +5,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
         qed_selftest.o qed_dcbx.o qed_debug.o
 qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
 qed-$(CONFIG_QED_LL2) += qed_ll2.o
-qed-$(CONFIG_INFINIBAND_QEDR) += qed_roce.o
+qed-$(CONFIG_QED_RDMA) += qed_roce.o
index 82370a1..0c42c24 100644 (file)
 #define TM_ALIGN        BIT(TM_SHIFT)
 #define TM_ELEM_SIZE    4
 
-/* ILT constants */
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
 /* For RoCE we configure to 64K to cover for RoCE max tasks 256K purpose. */
-#define ILT_DEFAULT_HW_P_SIZE          4
-#else
-#define ILT_DEFAULT_HW_P_SIZE          3
-#endif
+#define ILT_DEFAULT_HW_P_SIZE  (IS_ENABLED(CONFIG_QED_RDMA) ? 4 : 3)
 
 #define ILT_PAGE_IN_BYTES(hw_p_size)   (1U << ((hw_p_size) + 12))
 #define ILT_CFG_REG(cli, reg)  PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET
@@ -349,14 +344,14 @@ static struct qed_tid_seg *qed_cxt_tid_seg_info(struct qed_hwfn *p_hwfn,
        return NULL;
 }
 
-void qed_cxt_set_srq_count(struct qed_hwfn *p_hwfn, u32 num_srqs)
+static void qed_cxt_set_srq_count(struct qed_hwfn *p_hwfn, u32 num_srqs)
 {
        struct qed_cxt_mngr *p_mgr = p_hwfn->p_cxt_mngr;
 
        p_mgr->srq_count = num_srqs;
 }
 
-u32 qed_cxt_get_srq_count(struct qed_hwfn *p_hwfn)
+static u32 qed_cxt_get_srq_count(struct qed_hwfn *p_hwfn)
 {
        struct qed_cxt_mngr *p_mgr = p_hwfn->p_cxt_mngr;
 
@@ -1804,8 +1799,8 @@ int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn, struct qed_cxt_info *p_info)
        return 0;
 }
 
-void qed_rdma_set_pf_params(struct qed_hwfn *p_hwfn,
-                           struct qed_rdma_pf_params *p_params)
+static void qed_rdma_set_pf_params(struct qed_hwfn *p_hwfn,
+                                  struct qed_rdma_pf_params *p_params)
 {
        u32 num_cons, num_tasks, num_qps, num_mrs, num_srqs;
        enum protocol_type proto;
index 130da1c..a4789a9 100644 (file)
@@ -1190,6 +1190,7 @@ int qed_dcbx_get_config_params(struct qed_hwfn *p_hwfn,
        if (!dcbx_info)
                return -ENOMEM;
 
+       memset(dcbx_info, 0, sizeof(*dcbx_info));
        rc = qed_dcbx_query_params(p_hwfn, dcbx_info, QED_DCBX_OPERATIONAL_MIB);
        if (rc) {
                kfree(dcbx_info);
@@ -1225,6 +1226,7 @@ static struct qed_dcbx_get *qed_dcbnl_get_dcbx(struct qed_hwfn *hwfn,
        if (!dcbx_info)
                return NULL;
 
+       memset(dcbx_info, 0, sizeof(*dcbx_info));
        if (qed_dcbx_query_params(hwfn, dcbx_info, type)) {
                kfree(dcbx_info);
                return NULL;
index 88e7d5b..68f19ca 100644 (file)
@@ -405,7 +405,7 @@ struct phy_defs {
 /***************************** Constant Arrays *******************************/
 
 /* Debug arrays */
-static struct dbg_array s_dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE] = { {0} };
+static struct dbg_array s_dbg_arrays[MAX_BIN_DBG_BUFFER_TYPE] = { {NULL} };
 
 /* Chip constant definitions array */
 static struct chip_defs s_chip_defs[MAX_CHIP_IDS] = {
@@ -4028,10 +4028,10 @@ static enum dbg_status qed_mcp_trace_read_meta(struct qed_hwfn *p_hwfn,
 }
 
 /* Dump MCP Trace */
-enum dbg_status qed_mcp_trace_dump(struct qed_hwfn *p_hwfn,
-                                  struct qed_ptt *p_ptt,
-                                  u32 *dump_buf,
-                                  bool dump, u32 *num_dumped_dwords)
+static enum dbg_status qed_mcp_trace_dump(struct qed_hwfn *p_hwfn,
+                                         struct qed_ptt *p_ptt,
+                                         u32 *dump_buf,
+                                         bool dump, u32 *num_dumped_dwords)
 {
        u32 trace_data_grc_addr, trace_data_size_bytes, trace_data_size_dwords;
        u32 trace_meta_size_dwords, running_bundle_id, offset = 0;
@@ -4130,10 +4130,10 @@ enum dbg_status qed_mcp_trace_dump(struct qed_hwfn *p_hwfn,
 }
 
 /* Dump GRC FIFO */
-enum dbg_status qed_reg_fifo_dump(struct qed_hwfn *p_hwfn,
-                                 struct qed_ptt *p_ptt,
-                                 u32 *dump_buf,
-                                 bool dump, u32 *num_dumped_dwords)
+static enum dbg_status qed_reg_fifo_dump(struct qed_hwfn *p_hwfn,
+                                        struct qed_ptt *p_ptt,
+                                        u32 *dump_buf,
+                                        bool dump, u32 *num_dumped_dwords)
 {
        u32 offset = 0, dwords_read, size_param_offset;
        bool fifo_has_data;
@@ -4192,10 +4192,10 @@ enum dbg_status qed_reg_fifo_dump(struct qed_hwfn *p_hwfn,
 }
 
 /* Dump IGU FIFO */
-enum dbg_status qed_igu_fifo_dump(struct qed_hwfn *p_hwfn,
-                                 struct qed_ptt *p_ptt,
-                                 u32 *dump_buf,
-                                 bool dump, u32 *num_dumped_dwords)
+static enum dbg_status qed_igu_fifo_dump(struct qed_hwfn *p_hwfn,
+                                        struct qed_ptt *p_ptt,
+                                        u32 *dump_buf,
+                                        bool dump, u32 *num_dumped_dwords)
 {
        u32 offset = 0, dwords_read, size_param_offset;
        bool fifo_has_data;
@@ -4255,10 +4255,11 @@ enum dbg_status qed_igu_fifo_dump(struct qed_hwfn *p_hwfn,
 }
 
 /* Protection Override dump */
-enum dbg_status qed_protection_override_dump(struct qed_hwfn *p_hwfn,
-                                            struct qed_ptt *p_ptt,
-                                            u32 *dump_buf,
-                                            bool dump, u32 *num_dumped_dwords)
+static enum dbg_status qed_protection_override_dump(struct qed_hwfn *p_hwfn,
+                                                   struct qed_ptt *p_ptt,
+                                                   u32 *dump_buf,
+                                                   bool dump,
+                                                   u32 *num_dumped_dwords)
 {
        u32 offset = 0, size_param_offset, override_window_dwords;
 
@@ -6339,10 +6340,11 @@ enum dbg_status qed_print_fw_asserts_results(struct qed_hwfn *p_hwfn,
 }
 
 /* Wrapper for unifying the idle_chk and mcp_trace api */
-enum dbg_status qed_print_idle_chk_results_wrapper(struct qed_hwfn *p_hwfn,
-                                                  u32 *dump_buf,
-                                                  u32 num_dumped_dwords,
-                                                  char *results_buf)
+static enum dbg_status
+qed_print_idle_chk_results_wrapper(struct qed_hwfn *p_hwfn,
+                                  u32 *dump_buf,
+                                  u32 num_dumped_dwords,
+                                  char *results_buf)
 {
        u32 num_errors, num_warnnings;
 
@@ -6413,8 +6415,8 @@ static void qed_dbg_print_feature(u8 *p_text_buf, u32 text_size)
 
 #define QED_RESULTS_BUF_MIN_SIZE 16
 /* Generic function for decoding debug feature info */
-enum dbg_status format_feature(struct qed_hwfn *p_hwfn,
-                              enum qed_dbg_features feature_idx)
+static enum dbg_status format_feature(struct qed_hwfn *p_hwfn,
+                                     enum qed_dbg_features feature_idx)
 {
        struct qed_dbg_feature *feature =
            &p_hwfn->cdev->dbg_params.features[feature_idx];
@@ -6480,8 +6482,9 @@ enum dbg_status format_feature(struct qed_hwfn *p_hwfn,
 }
 
 /* Generic function for performing the dump of a debug feature. */
-enum dbg_status qed_dbg_dump(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
-                            enum qed_dbg_features feature_idx)
+static enum dbg_status qed_dbg_dump(struct qed_hwfn *p_hwfn,
+                                   struct qed_ptt *p_ptt,
+                                   enum qed_dbg_features feature_idx)
 {
        struct qed_dbg_feature *feature =
            &p_hwfn->cdev->dbg_params.features[feature_idx];
index 754f6a9..edae5fc 100644 (file)
@@ -497,12 +497,13 @@ int qed_resc_alloc(struct qed_dev *cdev)
                if (p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE) {
                        num_cons = qed_cxt_get_proto_cid_count(p_hwfn,
                                                               PROTOCOLID_ROCE,
-                                                              0) * 2;
+                                                              NULL) * 2;
                        n_eqes += num_cons + 2 * MAX_NUM_VFS_BB;
                } else if (p_hwfn->hw_info.personality == QED_PCI_ISCSI) {
                        num_cons =
                            qed_cxt_get_proto_cid_count(p_hwfn,
-                                                       PROTOCOLID_ISCSI, 0);
+                                                       PROTOCOLID_ISCSI,
+                                                       NULL);
                        n_eqes += 2 * num_cons;
                }
 
@@ -1422,19 +1423,19 @@ static void qed_hw_set_feat(struct qed_hwfn *p_hwfn)
        u32 *feat_num = p_hwfn->hw_info.feat_num;
        int num_features = 1;
 
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
-       /* Roce CNQ each requires: 1 status block + 1 CNQ. We divide the
-        * status blocks equally between L2 / RoCE but with consideration as
-        * to how many l2 queues / cnqs we have
-        */
-       if (p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE) {
+       if (IS_ENABLED(CONFIG_QED_RDMA) &&
+           p_hwfn->hw_info.personality == QED_PCI_ETH_ROCE) {
+               /* Roce CNQ each requires: 1 status block + 1 CNQ. We divide
+                * the status blocks equally between L2 / RoCE but with
+                * consideration as to how many l2 queues / cnqs we have.
+                */
                num_features++;
 
                feat_num[QED_RDMA_CNQ] =
                        min_t(u32, RESC_NUM(p_hwfn, QED_SB) / num_features,
                              RESC_NUM(p_hwfn, QED_RDMA_CNQ_RAM));
        }
-#endif
+
        feat_num[QED_PF_L2_QUE] = min_t(u32, RESC_NUM(p_hwfn, QED_SB) /
                                                num_features,
                                        RESC_NUM(p_hwfn, QED_L2_QUEUE));
index 02a8be2..63e1a1b 100644 (file)
@@ -38,6 +38,7 @@
 #include "qed_mcp.h"
 #include "qed_reg_addr.h"
 #include "qed_sp.h"
+#include "qed_roce.h"
 
 #define QED_LL2_RX_REGISTERED(ll2)     ((ll2)->rx_queue.b_cb_registred)
 #define QED_LL2_TX_REGISTERED(ll2)     ((ll2)->tx_queue.b_cb_registred)
@@ -140,11 +141,11 @@ static void qed_ll2_kill_buffers(struct qed_dev *cdev)
                qed_ll2_dealloc_buffer(cdev, buffer);
 }
 
-void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
-                                u8 connection_handle,
-                                struct qed_ll2_rx_packet *p_pkt,
-                                struct core_rx_fast_path_cqe *p_cqe,
-                                bool b_last_packet)
+static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
+                                       u8 connection_handle,
+                                       struct qed_ll2_rx_packet *p_pkt,
+                                       struct core_rx_fast_path_cqe *p_cqe,
+                                       bool b_last_packet)
 {
        u16 packet_length = le16_to_cpu(p_cqe->packet_length);
        struct qed_ll2_buffer *buffer = p_pkt->cookie;
@@ -515,7 +516,7 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
        return rc;
 }
 
-void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
+static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
 {
        struct qed_ll2_info *p_ll2_conn = NULL;
        struct qed_ll2_rx_packet *p_pkt = NULL;
@@ -537,8 +538,7 @@ void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
                if (!p_pkt)
                        break;
 
-               list_del(&p_pkt->list_entry);
-               list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
+               list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);
 
                rx_buf_addr = p_pkt->rx_buf_addr;
                cookie = p_pkt->cookie;
@@ -992,9 +992,8 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
                p_posting_packet = list_first_entry(&p_rx->posting_descq,
                                                    struct qed_ll2_rx_packet,
                                                    list_entry);
-               list_del(&p_posting_packet->list_entry);
-               list_add_tail(&p_posting_packet->list_entry,
-                             &p_rx->active_descq);
+               list_move_tail(&p_posting_packet->list_entry,
+                              &p_rx->active_descq);
                b_notify_fw = true;
        }
 
@@ -1123,9 +1122,6 @@ static void qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
        DMA_REGPAIR_LE(start_bd->addr, first_frag);
        start_bd->nbytes = cpu_to_le16(first_frag_len);
 
-       SET_FIELD(start_bd->bd_flags.as_bitfield, CORE_TX_BD_FLAGS_ROCE_FLAV,
-                 type);
-
        DP_VERBOSE(p_hwfn,
                   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
                   "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",
@@ -1188,8 +1184,7 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,
                if (!p_pkt)
                        break;
 
-               list_del(&p_pkt->list_entry);
-               list_add_tail(&p_pkt->list_entry, &p_tx->active_descq);
+               list_move_tail(&p_pkt->list_entry, &p_tx->active_descq);
        }
 
        SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);
index 80a5dc2..4e3d62a 100644 (file)
@@ -293,24 +293,4 @@ void qed_ll2_setup(struct qed_hwfn *p_hwfn,
  */
 void qed_ll2_free(struct qed_hwfn *p_hwfn,
                  struct qed_ll2_info *p_ll2_connections);
-void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t rx_buf_addr,
-                                    u16 data_length,
-                                    u8 data_length_error,
-                                    u16 parse_flags,
-                                    u16 vlan,
-                                    u32 src_mac_addr_hi,
-                                    u16 src_mac_addr_lo, bool b_last_packet);
-void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                    u8 connection_handle,
-                                    void *cookie,
-                                    dma_addr_t first_frag_addr,
-                                    bool b_last_fragment, bool b_last_packet);
-void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
-                                   u8 connection_handle,
-                                   void *cookie,
-                                   dma_addr_t first_frag_addr,
-                                   bool b_last_fragment, bool b_last_packet);
 #endif
index 4ee3151..c418360 100644 (file)
 #include "qed_hw.h"
 #include "qed_selftest.h"
 
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
 #define QED_ROCE_QPS                   (8192)
 #define QED_ROCE_DPIS                  (8)
-#endif
 
 static char version[] =
        "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n";
@@ -682,9 +680,7 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev,
                                  enum qed_int_mode int_mode)
 {
        struct qed_sb_cnt_info sb_cnt_info;
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
-       int num_l2_queues;
-#endif
+       int num_l2_queues = 0;
        int rc;
        int i;
 
@@ -715,8 +711,9 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev,
        cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors -
                                       cdev->num_hwfns;
 
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
-       num_l2_queues = 0;
+       if (!IS_ENABLED(CONFIG_QED_RDMA))
+               return 0;
+
        for_each_hwfn(cdev, i)
                num_l2_queues += FEAT_NUM(&cdev->hwfns[i], QED_PF_L2_QUE);
 
@@ -738,7 +735,6 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev,
        DP_VERBOSE(cdev, QED_MSG_RDMA, "roce_msix_cnt=%d roce_msix_base=%d\n",
                   cdev->int_params.rdma_msix_cnt,
                   cdev->int_params.rdma_msix_base);
-#endif
 
        return 0;
 }
@@ -843,18 +839,20 @@ static void qed_update_pf_params(struct qed_dev *cdev,
 {
        int i;
 
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
-       params->rdma_pf_params.num_qps = QED_ROCE_QPS;
-       params->rdma_pf_params.min_dpis = QED_ROCE_DPIS;
-       /* divide by 3 the MRs to avoid MF ILT overflow */
-       params->rdma_pf_params.num_mrs = RDMA_MAX_TIDS;
-       params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX;
-#endif
        for (i = 0; i < cdev->num_hwfns; i++) {
                struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
 
                p_hwfn->pf_params = *params;
        }
+
+       if (!IS_ENABLED(CONFIG_QED_RDMA))
+               return;
+
+       params->rdma_pf_params.num_qps = QED_ROCE_QPS;
+       params->rdma_pf_params.min_dpis = QED_ROCE_DPIS;
+       /* divide by 3 the MRs to avoid MF ILT overflow */
+       params->rdma_pf_params.num_mrs = RDMA_MAX_TIDS;
+       params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX;
 }
 
 static int qed_slowpath_start(struct qed_dev *cdev,
@@ -880,6 +878,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
                }
        }
 
+       cdev->rx_coalesce_usecs = QED_DEFAULT_RX_USECS;
        rc = qed_nic_setup(cdev);
        if (rc)
                goto err;
@@ -1432,7 +1431,7 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
        return status;
 }
 
-struct qed_selftest_ops qed_selftest_ops_pass = {
+static struct qed_selftest_ops qed_selftest_ops_pass = {
        .selftest_memory = &qed_selftest_memory,
        .selftest_interrupt = &qed_selftest_interrupt,
        .selftest_register = &qed_selftest_register,
index 76831a3..f3a825a 100644 (file)
@@ -129,17 +129,12 @@ static void qed_bmap_release_id(struct qed_hwfn *p_hwfn,
        }
 }
 
-u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id)
+static u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id)
 {
        /* First sb id for RoCE is after all the l2 sb */
        return FEAT_NUM((struct qed_hwfn *)p_hwfn, QED_PF_L2_QUE) + rel_sb_id;
 }
 
-u32 qed_rdma_query_cau_timer_res(void *rdma_cxt)
-{
-       return QED_CAU_DEF_RX_TIMER_RES;
-}
-
 static int qed_rdma_alloc(struct qed_hwfn *p_hwfn,
                          struct qed_ptt *p_ptt,
                          struct qed_rdma_start_in_params *params)
@@ -162,7 +157,8 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn,
        p_hwfn->p_rdma_info = p_rdma_info;
        p_rdma_info->proto = PROTOCOLID_ROCE;
 
-       num_cons = qed_cxt_get_proto_cid_count(p_hwfn, p_rdma_info->proto, 0);
+       num_cons = qed_cxt_get_proto_cid_count(p_hwfn, p_rdma_info->proto,
+                                              NULL);
 
        p_rdma_info->num_qps = num_cons / 2;
 
@@ -275,7 +271,7 @@ free_rdma_info:
        return rc;
 }
 
-void qed_rdma_resc_free(struct qed_hwfn *p_hwfn)
+static void qed_rdma_resc_free(struct qed_hwfn *p_hwfn)
 {
        struct qed_rdma_info *p_rdma_info = p_hwfn->p_rdma_info;
 
@@ -527,6 +523,26 @@ static int qed_rdma_start_fw(struct qed_hwfn *p_hwfn,
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
+static int qed_rdma_alloc_tid(void *rdma_cxt, u32 *itid)
+{
+       struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
+       int rc;
+
+       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocate TID\n");
+
+       spin_lock_bh(&p_hwfn->p_rdma_info->lock);
+       rc = qed_rdma_bmap_alloc_id(p_hwfn,
+                                   &p_hwfn->p_rdma_info->tid_map, itid);
+       spin_unlock_bh(&p_hwfn->p_rdma_info->lock);
+       if (rc)
+               goto out;
+
+       rc = qed_cxt_dynamic_ilt_alloc(p_hwfn, QED_ELEM_TASK, *itid);
+out:
+       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocate TID - done, rc = %d\n", rc);
+       return rc;
+}
+
 static int qed_rdma_reserve_lkey(struct qed_hwfn *p_hwfn)
 {
        struct qed_rdma_device *dev = p_hwfn->p_rdma_info->dev;
@@ -573,7 +589,7 @@ static int qed_rdma_setup(struct qed_hwfn *p_hwfn,
        return qed_rdma_start_fw(p_hwfn, params, p_ptt);
 }
 
-int qed_rdma_stop(void *rdma_cxt)
+static int qed_rdma_stop(void *rdma_cxt)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct rdma_close_func_ramrod_data *p_ramrod;
@@ -629,8 +645,8 @@ out:
        return rc;
 }
 
-int qed_rdma_add_user(void *rdma_cxt,
-                     struct qed_rdma_add_user_out_params *out_params)
+static int qed_rdma_add_user(void *rdma_cxt,
+                            struct qed_rdma_add_user_out_params *out_params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        u32 dpi_start_offset;
@@ -664,7 +680,7 @@ int qed_rdma_add_user(void *rdma_cxt,
        return rc;
 }
 
-struct qed_rdma_port *qed_rdma_query_port(void *rdma_cxt)
+static struct qed_rdma_port *qed_rdma_query_port(void *rdma_cxt)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct qed_rdma_port *p_port = p_hwfn->p_rdma_info->port;
@@ -680,7 +696,7 @@ struct qed_rdma_port *qed_rdma_query_port(void *rdma_cxt)
        return p_port;
 }
 
-struct qed_rdma_device *qed_rdma_query_device(void *rdma_cxt)
+static struct qed_rdma_device *qed_rdma_query_device(void *rdma_cxt)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
 
@@ -690,7 +706,7 @@ struct qed_rdma_device *qed_rdma_query_device(void *rdma_cxt)
        return p_hwfn->p_rdma_info->dev;
 }
 
-void qed_rdma_free_tid(void *rdma_cxt, u32 itid)
+static void qed_rdma_free_tid(void *rdma_cxt, u32 itid)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
 
@@ -701,27 +717,7 @@ void qed_rdma_free_tid(void *rdma_cxt, u32 itid)
        spin_unlock_bh(&p_hwfn->p_rdma_info->lock);
 }
 
-int qed_rdma_alloc_tid(void *rdma_cxt, u32 *itid)
-{
-       struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
-       int rc;
-
-       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocate TID\n");
-
-       spin_lock_bh(&p_hwfn->p_rdma_info->lock);
-       rc = qed_rdma_bmap_alloc_id(p_hwfn,
-                                   &p_hwfn->p_rdma_info->tid_map, itid);
-       spin_unlock_bh(&p_hwfn->p_rdma_info->lock);
-       if (rc)
-               goto out;
-
-       rc = qed_cxt_dynamic_ilt_alloc(p_hwfn, QED_ELEM_TASK, *itid);
-out:
-       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocate TID - done, rc = %d\n", rc);
-       return rc;
-}
-
-void qed_rdma_cnq_prod_update(void *rdma_cxt, u8 qz_offset, u16 prod)
+static void qed_rdma_cnq_prod_update(void *rdma_cxt, u8 qz_offset, u16 prod)
 {
        struct qed_hwfn *p_hwfn;
        u16 qz_num;
@@ -816,7 +812,7 @@ static int qed_rdma_get_int(struct qed_dev *cdev, struct qed_int_info *info)
        return 0;
 }
 
-int qed_rdma_alloc_pd(void *rdma_cxt, u16 *pd)
+static int qed_rdma_alloc_pd(void *rdma_cxt, u16 *pd)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        u32 returned_id;
@@ -836,7 +832,7 @@ int qed_rdma_alloc_pd(void *rdma_cxt, u16 *pd)
        return rc;
 }
 
-void qed_rdma_free_pd(void *rdma_cxt, u16 pd)
+static void qed_rdma_free_pd(void *rdma_cxt, u16 pd)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
 
@@ -873,8 +869,9 @@ qed_rdma_toggle_bit_create_resize_cq(struct qed_hwfn *p_hwfn, u16 icid)
        return toggle_bit;
 }
 
-int qed_rdma_create_cq(void *rdma_cxt,
-                      struct qed_rdma_create_cq_in_params *params, u16 *icid)
+static int qed_rdma_create_cq(void *rdma_cxt,
+                             struct qed_rdma_create_cq_in_params *params,
+                             u16 *icid)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct qed_rdma_info *p_info = p_hwfn->p_rdma_info;
@@ -957,98 +954,10 @@ err:
        return rc;
 }
 
-int qed_rdma_resize_cq(void *rdma_cxt,
-                      struct qed_rdma_resize_cq_in_params *in_params,
-                      struct qed_rdma_resize_cq_out_params *out_params)
-{
-       struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
-       struct rdma_resize_cq_output_params *p_ramrod_res;
-       struct rdma_resize_cq_ramrod_data *p_ramrod;
-       enum qed_rdma_toggle_bit toggle_bit;
-       struct qed_sp_init_data init_data;
-       struct qed_spq_entry *p_ent;
-       dma_addr_t ramrod_res_phys;
-       u8 fw_return_code;
-       int rc = -ENOMEM;
-
-       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "icid = %08x\n", in_params->icid);
-
-       p_ramrod_res =
-           (struct rdma_resize_cq_output_params *)
-           dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
-                              sizeof(struct rdma_resize_cq_output_params),
-                              &ramrod_res_phys, GFP_KERNEL);
-       if (!p_ramrod_res) {
-               DP_NOTICE(p_hwfn,
-                         "qed resize cq failed: cannot allocate memory (ramrod)\n");
-               return rc;
-       }
-
-       /* Get SPQ entry */
-       memset(&init_data, 0, sizeof(init_data));
-       init_data.cid = in_params->icid;
-       init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
-       init_data.comp_mode = QED_SPQ_MODE_EBLOCK;
-
-       rc = qed_sp_init_request(p_hwfn, &p_ent,
-                                RDMA_RAMROD_RESIZE_CQ,
-                                p_hwfn->p_rdma_info->proto, &init_data);
-       if (rc)
-               goto err;
-
-       p_ramrod = &p_ent->ramrod.rdma_resize_cq;
-
-       p_ramrod->flags = 0;
-
-       /* toggle the bit for every resize or create cq for a given icid */
-       toggle_bit = qed_rdma_toggle_bit_create_resize_cq(p_hwfn,
-                                                         in_params->icid);
-
-       SET_FIELD(p_ramrod->flags,
-                 RDMA_RESIZE_CQ_RAMROD_DATA_TOGGLE_BIT, toggle_bit);
-
-       SET_FIELD(p_ramrod->flags,
-                 RDMA_RESIZE_CQ_RAMROD_DATA_IS_TWO_LEVEL_PBL,
-                 in_params->pbl_two_level);
-
-       p_ramrod->pbl_log_page_size = in_params->pbl_page_size_log - 12;
-       p_ramrod->pbl_num_pages = cpu_to_le16(in_params->pbl_num_pages);
-       p_ramrod->max_cqes = cpu_to_le32(in_params->cq_size);
-       DMA_REGPAIR_LE(p_ramrod->pbl_addr, in_params->pbl_ptr);
-       DMA_REGPAIR_LE(p_ramrod->output_params_addr, ramrod_res_phys);
-
-       rc = qed_spq_post(p_hwfn, p_ent, &fw_return_code);
-       if (rc)
-               goto err;
-
-       if (fw_return_code != RDMA_RETURN_OK) {
-               DP_NOTICE(p_hwfn, "fw_return_code = %d\n", fw_return_code);
-               rc = -EINVAL;
-               goto err;
-       }
-
-       out_params->prod = le32_to_cpu(p_ramrod_res->old_cq_prod);
-       out_params->cons = le32_to_cpu(p_ramrod_res->old_cq_cons);
-
-       dma_free_coherent(&p_hwfn->cdev->pdev->dev,
-                         sizeof(struct rdma_resize_cq_output_params),
-                         p_ramrod_res, ramrod_res_phys);
-
-       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Resized CQ, rc = %d\n", rc);
-
-       return rc;
-
-err:   dma_free_coherent(&p_hwfn->cdev->pdev->dev,
-                         sizeof(struct rdma_resize_cq_output_params),
-                         p_ramrod_res, ramrod_res_phys);
-       DP_NOTICE(p_hwfn, "Resized CQ, Failed - rc = %d\n", rc);
-
-       return rc;
-}
-
-int qed_rdma_destroy_cq(void *rdma_cxt,
-                       struct qed_rdma_destroy_cq_in_params *in_params,
-                       struct qed_rdma_destroy_cq_out_params *out_params)
+static int
+qed_rdma_destroy_cq(void *rdma_cxt,
+                   struct qed_rdma_destroy_cq_in_params *in_params,
+                   struct qed_rdma_destroy_cq_out_params *out_params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct rdma_destroy_cq_output_params *p_ramrod_res;
@@ -1169,7 +1078,7 @@ static enum roce_flavor qed_roce_mode_to_flavor(enum roce_mode roce_mode)
        return flavor;
 }
 
-int qed_roce_alloc_cid(struct qed_hwfn *p_hwfn, u16 *cid)
+static int qed_roce_alloc_cid(struct qed_hwfn *p_hwfn, u16 *cid)
 {
        struct qed_rdma_info *p_rdma_info = p_hwfn->p_rdma_info;
        u32 responder_icid;
@@ -1793,9 +1702,9 @@ err:
        return rc;
 }
 
-int qed_roce_query_qp(struct qed_hwfn *p_hwfn,
-                     struct qed_rdma_qp *qp,
-                     struct qed_rdma_query_qp_out_params *out_params)
+static int qed_roce_query_qp(struct qed_hwfn *p_hwfn,
+                            struct qed_rdma_qp *qp,
+                            struct qed_rdma_query_qp_out_params *out_params)
 {
        struct roce_query_qp_resp_output_params *p_resp_ramrod_res;
        struct roce_query_qp_req_output_params *p_req_ramrod_res;
@@ -1936,7 +1845,7 @@ err_resp:
        return rc;
 }
 
-int qed_roce_destroy_qp(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp)
+static int qed_roce_destroy_qp(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp)
 {
        u32 num_invalidated_mw = 0;
        u32 num_bound_mw = 0;
@@ -1985,9 +1894,9 @@ int qed_roce_destroy_qp(struct qed_hwfn *p_hwfn, struct qed_rdma_qp *qp)
        return 0;
 }
 
-int qed_rdma_query_qp(void *rdma_cxt,
-                     struct qed_rdma_qp *qp,
-                     struct qed_rdma_query_qp_out_params *out_params)
+static int qed_rdma_query_qp(void *rdma_cxt,
+                            struct qed_rdma_qp *qp,
+                            struct qed_rdma_query_qp_out_params *out_params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        int rc;
@@ -2022,7 +1931,7 @@ int qed_rdma_query_qp(void *rdma_cxt,
        return rc;
 }
 
-int qed_rdma_destroy_qp(void *rdma_cxt, struct qed_rdma_qp *qp)
+static int qed_rdma_destroy_qp(void *rdma_cxt, struct qed_rdma_qp *qp)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        int rc = 0;
@@ -2038,7 +1947,7 @@ int qed_rdma_destroy_qp(void *rdma_cxt, struct qed_rdma_qp *qp)
        return rc;
 }
 
-struct qed_rdma_qp *
+static struct qed_rdma_qp *
 qed_rdma_create_qp(void *rdma_cxt,
                   struct qed_rdma_create_qp_in_params *in_params,
                   struct qed_rdma_create_qp_out_params *out_params)
@@ -2215,9 +2124,9 @@ static int qed_roce_modify_qp(struct qed_hwfn *p_hwfn,
        return rc;
 }
 
-int qed_rdma_modify_qp(void *rdma_cxt,
-                      struct qed_rdma_qp *qp,
-                      struct qed_rdma_modify_qp_in_params *params)
+static int qed_rdma_modify_qp(void *rdma_cxt,
+                             struct qed_rdma_qp *qp,
+                             struct qed_rdma_modify_qp_in_params *params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        enum qed_roce_qp_state prev_state;
@@ -2312,8 +2221,9 @@ int qed_rdma_modify_qp(void *rdma_cxt,
        return rc;
 }
 
-int qed_rdma_register_tid(void *rdma_cxt,
-                         struct qed_rdma_register_tid_in_params *params)
+static int
+qed_rdma_register_tid(void *rdma_cxt,
+                     struct qed_rdma_register_tid_in_params *params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct rdma_register_tid_ramrod_data *p_ramrod;
@@ -2450,7 +2360,7 @@ int qed_rdma_register_tid(void *rdma_cxt,
        return rc;
 }
 
-int qed_rdma_deregister_tid(void *rdma_cxt, u32 itid)
+static int qed_rdma_deregister_tid(void *rdma_cxt, u32 itid)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct rdma_deregister_tid_ramrod_data *p_ramrod;
@@ -2561,7 +2471,8 @@ void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        qed_rdma_dpm_conf(p_hwfn, p_ptt);
 }
 
-int qed_rdma_start(void *rdma_cxt, struct qed_rdma_start_in_params *params)
+static int qed_rdma_start(void *rdma_cxt,
+                         struct qed_rdma_start_in_params *params)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
        struct qed_ptt *p_ptt;
@@ -2601,7 +2512,7 @@ static int qed_rdma_init(struct qed_dev *cdev,
        return qed_rdma_start(QED_LEADING_HWFN(cdev), params);
 }
 
-void qed_rdma_remove_user(void *rdma_cxt, u16 dpi)
+static void qed_rdma_remove_user(void *rdma_cxt, u16 dpi)
 {
        struct qed_hwfn *p_hwfn = (struct qed_hwfn *)rdma_cxt;
 
@@ -2809,11 +2720,6 @@ static int qed_roce_ll2_stop(struct qed_dev *cdev)
        struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2;
        int rc;
 
-       if (!cdev) {
-               DP_ERR(cdev, "qed roce ll2 stop: invalid cdev\n");
-               return -EINVAL;
-       }
-
        if (roce_ll2->handle == QED_LL2_UNUSED_HANDLE) {
                DP_ERR(cdev, "qed roce ll2 stop: cannot stop an unused LL2\n");
                return -EINVAL;
@@ -2850,7 +2756,7 @@ static int qed_roce_ll2_tx(struct qed_dev *cdev,
        int rc;
        int i;
 
-       if (!cdev || !pkt || !params) {
+       if (!pkt || !params) {
                DP_ERR(cdev,
                       "roce ll2 tx: failed tx because one of the following is NULL - drv=%p, pkt=%p, params=%p\n",
                       cdev, pkt, params);
index 2f091e8..279f342 100644 (file)
@@ -95,26 +95,6 @@ struct qed_rdma_info {
        enum protocol_type proto;
 };
 
-struct qed_rdma_resize_cq_in_params {
-       u16 icid;
-       u32 cq_size;
-       bool pbl_two_level;
-       u64 pbl_ptr;
-       u16 pbl_num_pages;
-       u8 pbl_page_size_log;
-};
-
-struct qed_rdma_resize_cq_out_params {
-       u32 prod;
-       u32 cons;
-};
-
-struct qed_rdma_resize_cnq_in_params {
-       u32 cnq_id;
-       u32 pbl_page_size_log;
-       u64 pbl_ptr;
-};
-
 struct qed_rdma_qp {
        struct regpair qp_handle;
        struct regpair qp_handle_async;
@@ -181,36 +161,55 @@ struct qed_rdma_qp {
        dma_addr_t shared_queue_phys_addr;
 };
 
-int
-qed_rdma_add_user(void *rdma_cxt,
-                 struct qed_rdma_add_user_out_params *out_params);
-int qed_rdma_alloc_pd(void *rdma_cxt, u16 *pd);
-int qed_rdma_alloc_tid(void *rdma_cxt, u32 *tid);
-int qed_rdma_deregister_tid(void *rdma_cxt, u32 tid);
-void qed_rdma_free_tid(void *rdma_cxt, u32 tid);
-struct qed_rdma_device *qed_rdma_query_device(void *rdma_cxt);
-struct qed_rdma_port *qed_rdma_query_port(void *rdma_cxt);
-int
-qed_rdma_register_tid(void *rdma_cxt,
-                     struct qed_rdma_register_tid_in_params *params);
-void qed_rdma_remove_user(void *rdma_cxt, u16 dpi);
-int qed_rdma_start(void *p_hwfn, struct qed_rdma_start_in_params *params);
-int qed_rdma_stop(void *rdma_cxt);
-u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id);
-u32 qed_rdma_query_cau_timer_res(void *p_hwfn);
-void qed_rdma_cnq_prod_update(void *rdma_cxt, u8 cnq_index, u16 prod);
-void qed_rdma_resc_free(struct qed_hwfn *p_hwfn);
+#if IS_ENABLED(CONFIG_QED_RDMA)
+void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
 void qed_async_roce_event(struct qed_hwfn *p_hwfn,
                          struct event_ring_entry *p_eqe);
-int qed_rdma_destroy_qp(void *rdma_cxt, struct qed_rdma_qp *qp);
-int qed_rdma_modify_qp(void *rdma_cxt, struct qed_rdma_qp *qp,
-                      struct qed_rdma_modify_qp_in_params *params);
-int qed_rdma_query_qp(void *rdma_cxt, struct qed_rdma_qp *qp,
-                     struct qed_rdma_query_qp_out_params *out_params);
-
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
-void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                    u8 connection_handle,
+                                    void *cookie,
+                                    dma_addr_t first_frag_addr,
+                                    bool b_last_fragment, bool b_last_packet);
+void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                   u8 connection_handle,
+                                   void *cookie,
+                                   dma_addr_t first_frag_addr,
+                                   bool b_last_fragment, bool b_last_packet);
+void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                    u8 connection_handle,
+                                    void *cookie,
+                                    dma_addr_t rx_buf_addr,
+                                    u16 data_length,
+                                    u8 data_length_error,
+                                    u16 parse_flags,
+                                    u16 vlan,
+                                    u32 src_mac_addr_hi,
+                                    u16 src_mac_addr_lo, bool b_last_packet);
 #else
-void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}
+static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}
+static inline void qed_async_roce_event(struct qed_hwfn *p_hwfn, struct event_ring_entry *p_eqe) {}
+static inline void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                                  u8 connection_handle,
+                                                  void *cookie,
+                                                  dma_addr_t first_frag_addr,
+                                                  bool b_last_fragment,
+                                                  bool b_last_packet) {}
+static inline void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                                 u8 connection_handle,
+                                                 void *cookie,
+                                                 dma_addr_t first_frag_addr,
+                                                 bool b_last_fragment,
+                                                 bool b_last_packet) {}
+static inline void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn,
+                                                  u8 connection_handle,
+                                                  void *cookie,
+                                                  dma_addr_t rx_buf_addr,
+                                                  u16 data_length,
+                                                  u8 data_length_error,
+                                                  u16 parse_flags,
+                                                  u16 vlan,
+                                                  u32 src_mac_addr_hi,
+                                                  u16 src_mac_addr_lo,
+                                                  bool b_last_packet) {}
 #endif
 #endif
index 652c908..b2c08e4 100644 (file)
@@ -80,7 +80,6 @@ union ramrod_data {
        struct roce_destroy_qp_resp_ramrod_data roce_destroy_qp_resp;
        struct roce_destroy_qp_req_ramrod_data roce_destroy_qp_req;
        struct rdma_create_cq_ramrod_data rdma_create_cq;
-       struct rdma_resize_cq_ramrod_data rdma_resize_cq;
        struct rdma_destroy_cq_ramrod_data rdma_destroy_cq;
        struct rdma_srq_create_ramrod_data rdma_create_srq;
        struct rdma_srq_destroy_ramrod_data rdma_destroy_srq;
index caff415..9fbaf94 100644 (file)
@@ -28,9 +28,7 @@
 #include "qed_reg_addr.h"
 #include "qed_sp.h"
 #include "qed_sriov.h"
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
 #include "qed_roce.h"
-#endif
 
 /***************************************************************************
 * Structures & Definitions
@@ -240,11 +238,9 @@ qed_async_event_completion(struct qed_hwfn *p_hwfn,
                           struct event_ring_entry *p_eqe)
 {
        switch (p_eqe->protocol_id) {
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
        case PROTOCOLID_ROCE:
                qed_async_roce_event(p_hwfn, p_eqe);
                return 0;
-#endif
        case PROTOCOLID_COMMON:
                return qed_sriov_eqe_event(p_hwfn,
                                           p_eqe->opcode,
index 28dc589..048a230 100644 (file)
@@ -2,4 +2,4 @@ obj-$(CONFIG_QEDE) := qede.o
 
 qede-y := qede_main.o qede_ethtool.o
 qede-$(CONFIG_DCB) += qede_dcbnl.o
-qede-$(CONFIG_INFINIBAND_QEDR) += qede_roce.o
+qede-$(CONFIG_QED_RDMA) += qede_roce.o
index 28c0e9f..974689a 100644 (file)
@@ -348,12 +348,13 @@ bool qede_has_rx_work(struct qede_rx_queue *rxq);
 int qede_txq_has_work(struct qede_tx_queue *txq);
 void qede_recycle_rx_bd_ring(struct qede_rx_queue *rxq, struct qede_dev *edev,
                             u8 count);
+void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
 
 #define RX_RING_SIZE_POW       13
 #define RX_RING_SIZE           ((u16)BIT(RX_RING_SIZE_POW))
 #define NUM_RX_BDS_MAX         (RX_RING_SIZE - 1)
 #define NUM_RX_BDS_MIN         128
-#define NUM_RX_BDS_DEF         NUM_RX_BDS_MAX
+#define NUM_RX_BDS_DEF         ((u16)BIT(10) - 1)
 
 #define TX_RING_SIZE_POW       13
 #define TX_RING_SIZE           ((u16)BIT(TX_RING_SIZE_POW))
index 25a9b29..12251a1 100644 (file)
@@ -756,6 +756,8 @@ static void qede_get_channels(struct net_device *dev,
        struct qede_dev *edev = netdev_priv(dev);
 
        channels->max_combined = QEDE_MAX_RSS_CNT(edev);
+       channels->max_rx = QEDE_MAX_RSS_CNT(edev);
+       channels->max_tx = QEDE_MAX_RSS_CNT(edev);
        channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx -
                                        edev->fp_num_rx;
        channels->tx_count = edev->fp_num_tx;
@@ -820,6 +822,13 @@ static int qede_set_channels(struct net_device *dev,
        edev->req_queues = count;
        edev->req_num_tx = channels->tx_count;
        edev->req_num_rx = channels->rx_count;
+       /* Reset the indirection table if rx queue count is updated */
+       if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) {
+               edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED;
+               memset(&edev->rss_params.rss_ind_table, 0,
+                      sizeof(edev->rss_params.rss_ind_table));
+       }
+
        if (netif_running(dev))
                qede_reload(edev, NULL, NULL);
 
@@ -1053,6 +1062,12 @@ static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
        struct qede_dev *edev = netdev_priv(dev);
        int i;
 
+       if (edev->dev_info.common.num_hwfns > 1) {
+               DP_INFO(edev,
+                       "RSS configuration is not supported for 100G devices\n");
+               return -EOPNOTSUPP;
+       }
+
        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
                return -EOPNOTSUPP;
 
@@ -1184,8 +1199,8 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
        }
 
        first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
-       dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
-                      BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
+       dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+                        BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
        txq->sw_tx_cons++;
        txq->sw_tx_ring[idx].skb = NULL;
 
@@ -1199,8 +1214,8 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev)
        struct qede_rx_queue *rxq = NULL;
        struct sw_rx_data *sw_rx_data;
        union eth_rx_cqe *cqe;
+       int i, rc = 0;
        u8 *data_ptr;
-       int i;
 
        for_each_queue(i) {
                if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
@@ -1219,46 +1234,60 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev)
         * queue and that the loopback traffic is not IP.
         */
        for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
-               if (qede_has_rx_work(rxq))
+               if (!qede_has_rx_work(rxq)) {
+                       usleep_range(100, 200);
+                       continue;
+               }
+
+               hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
+               sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+
+               /* Memory barrier to prevent the CPU from doing speculative
+                * reads of CQE/BD before reading hw_comp_cons. If the CQE is
+                * read before it is written by FW, then FW writes CQE and SB,
+                * and then the CPU reads the hw_comp_cons, it will use an old
+                * CQE.
+                */
+               rmb();
+
+               /* Get the CQE from the completion ring */
+               cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
+
+               /* Get the data from the SW ring */
+               sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
+               sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
+               fp_cqe = &cqe->fast_path_regular;
+               len =  le16_to_cpu(fp_cqe->len_on_first_bd);
+               data_ptr = (u8 *)(page_address(sw_rx_data->data) +
+                                 fp_cqe->placement_offset +
+                                 sw_rx_data->page_offset);
+               if (ether_addr_equal(data_ptr,  edev->ndev->dev_addr) &&
+                   ether_addr_equal(data_ptr + ETH_ALEN,
+                                    edev->ndev->dev_addr)) {
+                       for (i = ETH_HLEN; i < len; i++)
+                               if (data_ptr[i] != (unsigned char)(i & 0xff)) {
+                                       rc = -1;
+                                       break;
+                               }
+
+                       qede_recycle_rx_bd_ring(rxq, edev, 1);
+                       qed_chain_recycle_consumed(&rxq->rx_comp_ring);
                        break;
-               usleep_range(100, 200);
+               }
+
+               DP_INFO(edev, "Not the transmitted packet\n");
+               qede_recycle_rx_bd_ring(rxq, edev, 1);
+               qed_chain_recycle_consumed(&rxq->rx_comp_ring);
        }
 
-       if (!qede_has_rx_work(rxq)) {
+       if (i == QEDE_SELFTEST_POLL_COUNT) {
                DP_NOTICE(edev, "Failed to receive the traffic\n");
                return -1;
        }
 
-       hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
-       sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
+       qede_update_rx_prod(edev, rxq);
 
-       /* Memory barrier to prevent the CPU from doing speculative reads of CQE
-        * / BD before reading hw_comp_cons. If the CQE is read before it is
-        * written by FW, then FW writes CQE and SB, and then the CPU reads the
-        * hw_comp_cons, it will use an old CQE.
-        */
-       rmb();
-
-       /* Get the CQE from the completion ring */
-       cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
-
-       /* Get the data from the SW ring */
-       sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
-       sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
-       fp_cqe = &cqe->fast_path_regular;
-       len =  le16_to_cpu(fp_cqe->len_on_first_bd);
-       data_ptr = (u8 *)(page_address(sw_rx_data->data) +
-                    fp_cqe->placement_offset + sw_rx_data->page_offset);
-       for (i = ETH_HLEN; i < len; i++)
-               if (data_ptr[i] != (unsigned char)(i & 0xff)) {
-                       DP_NOTICE(edev, "Loopback test failed\n");
-                       qede_recycle_rx_bd_ring(rxq, edev, 1);
-                       return -1;
-               }
-
-       qede_recycle_rx_bd_ring(rxq, edev, 1);
-
-       return 0;
+       return rc;
 }
 
 static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
index 343038c..7def29a 100644 (file)
@@ -313,8 +313,8 @@ static int qede_free_tx_pkt(struct qede_dev *edev,
                split_bd_len = BD_UNMAP_LEN(split);
                bds_consumed++;
        }
-       dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
-                      BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
+       dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+                        BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
 
        /* Unmap the data of the skb frags */
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, bds_consumed++) {
@@ -359,8 +359,8 @@ static void qede_free_failed_tx_pkt(struct qede_dev *edev,
                nbd--;
        }
 
-       dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
-                      BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
+       dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
+                        BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE);
 
        /* Unmap the data of the skb frags */
        for (i = 0; i < nbd; i++) {
@@ -943,8 +943,7 @@ static inline int qede_realloc_rx_buffer(struct qede_dev *edev,
        return 0;
 }
 
-static inline void qede_update_rx_prod(struct qede_dev *edev,
-                                      struct qede_rx_queue *rxq)
+void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq)
 {
        u16 bd_prod = qed_chain_get_prod_idx(&rxq->rx_bd_ring);
        u16 cqe_prod = qed_chain_get_prod_idx(&rxq->rx_comp_ring);
@@ -2941,7 +2940,7 @@ static int qede_alloc_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq)
        txq->num_tx_buffers = edev->q_num_tx_buffers;
 
        /* Allocate the parallel driver ring for Tx buffers */
-       size = sizeof(*txq->sw_tx_ring) * NUM_TX_BDS_MAX;
+       size = sizeof(*txq->sw_tx_ring) * TX_RING_SIZE;
        txq->sw_tx_ring = kzalloc(size, GFP_KERNEL);
        if (!txq->sw_tx_ring) {
                DP_NOTICE(edev, "Tx buffers ring allocation failed\n");
@@ -2952,7 +2951,7 @@ static int qede_alloc_mem_txq(struct qede_dev *edev, struct qede_tx_queue *txq)
                                            QED_CHAIN_USE_TO_CONSUME_PRODUCE,
                                            QED_CHAIN_MODE_PBL,
                                            QED_CHAIN_CNT_TYPE_U16,
-                                           NUM_TX_BDS_MAX,
+                                           TX_RING_SIZE,
                                            sizeof(*p_virt), &txq->tx_pbl);
        if (rc)
                goto err;
index e97968e..6fb3bee 100644 (file)
@@ -1021,14 +1021,18 @@ void emac_mac_down(struct emac_adapter *adpt)
        napi_disable(&adpt->rx_q.napi);
 
        phy_stop(adpt->phydev);
-       phy_disconnect(adpt->phydev);
 
-       /* disable mac irq */
+       /* Interrupts must be disabled before the PHY is disconnected, to
+        * avoid a race condition where adjust_link is null when we get
+        * an interrupt.
+        */
        writel(DIS_INT, adpt->base + EMAC_INT_STATUS);
        writel(0, adpt->base + EMAC_INT_MASK);
        synchronize_irq(adpt->irq.irq);
        free_irq(adpt->irq.irq, &adpt->irq);
 
+       phy_disconnect(adpt->phydev);
+
        emac_mac_reset(adpt);
 
        emac_tx_q_descs_free(adpt);
index 9bf3b2b..4fede4b 100644 (file)
@@ -575,6 +575,7 @@ static const struct of_device_id emac_dt_match[] = {
        },
        {}
 };
+MODULE_DEVICE_TABLE(of, emac_dt_match);
 
 #if IS_ENABLED(CONFIG_ACPI)
 static const struct acpi_device_id emac_acpi_match[] = {
index e55638c..bf000d8 100644 (file)
@@ -8273,7 +8273,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if ((sizeof(dma_addr_t) > 4) &&
            (use_dac == 1 || (use_dac == -1 && pci_is_pcie(pdev) &&
                              tp->mac_version >= RTL_GIGA_MAC_VER_18)) &&
-           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+           !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
+           !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
 
                /* CPlusCmd Dual Access Cycle is only needed for non-PCIe */
                if (!pci_is_pcie(pdev))
index 5424fb3..24b7464 100644 (file)
@@ -1471,7 +1471,7 @@ static int rocker_world_check_init(struct rocker_port *rocker_port)
        if (rocker->wops) {
                if (rocker->wops->mode != mode) {
                        dev_err(&rocker->pdev->dev, "hardware has ports in different worlds, which is not supported\n");
-                       return err;
+                       return -EINVAL;
                }
                return 0;
        }
index 431a608..4ca4613 100644 (file)
@@ -1493,8 +1493,6 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
        spin_lock_irqsave(&ofdpa->neigh_tbl_lock, lock_flags);
 
        found = ofdpa_neigh_tbl_find(ofdpa, ip_addr);
-       if (found)
-               *index = found->index;
 
        updating = found && adding;
        removing = found && !adding;
@@ -1508,9 +1506,11 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
                resolved = false;
        } else if (removing) {
                ofdpa_neigh_del(trans, found);
+               *index = found->index;
        } else if (updating) {
                ofdpa_neigh_update(found, trans, NULL, false);
                resolved = !is_zero_ether_addr(found->eth_dst);
+               *index = found->index;
        } else {
                err = -ENOENT;
        }
index 4ec7397..a1b17cd 100644 (file)
@@ -347,10 +347,9 @@ static void dwmac4_display_ring(void *head, unsigned int size, bool rx)
        pr_info("%s descriptor ring:\n", rx ? "RX" : "TX");
 
        for (i = 0; i < size; i++) {
-               if (p->des0)
-                       pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                               i, (unsigned int)virt_to_phys(p),
-                               p->des0, p->des1, p->des2, p->des3);
+               pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
+                       i, (unsigned int)virt_to_phys(p),
+                       p->des0, p->des1, p->des2, p->des3);
                p++;
        }
 }
index 8dc9056..b15fc55 100644 (file)
@@ -145,7 +145,7 @@ int stmmac_mdio_register(struct net_device *ndev);
 int stmmac_mdio_reset(struct mii_bus *mii);
 void stmmac_set_ethtool_ops(struct net_device *netdev);
 
-int stmmac_ptp_register(struct stmmac_priv *priv);
+void stmmac_ptp_register(struct stmmac_priv *priv);
 void stmmac_ptp_unregister(struct stmmac_priv *priv);
 int stmmac_resume(struct device *dev);
 int stmmac_suspend(struct device *dev);
index 6c85b61..48e71fa 100644 (file)
@@ -676,7 +676,9 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        priv->hwts_tx_en = 0;
        priv->hwts_rx_en = 0;
 
-       return stmmac_ptp_register(priv);
+       stmmac_ptp_register(priv);
+
+       return 0;
 }
 
 static void stmmac_release_ptp(struct stmmac_priv *priv)
@@ -1710,7 +1712,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
        if (init_ptp) {
                ret = stmmac_init_ptp(priv);
                if (ret)
-                       netdev_warn(priv->dev, "PTP support cannot init.\n");
+                       netdev_warn(priv->dev, "fail to init PTP.\n");
        }
 
 #ifdef CONFIG_DEBUG_FS
index 289d527..1477471 100644 (file)
@@ -177,7 +177,7 @@ static struct ptp_clock_info stmmac_ptp_clock_ops = {
  * Description: this function will register the ptp clock driver
  * to kernel. It also does some house keeping work.
  */
-int stmmac_ptp_register(struct stmmac_priv *priv)
+void stmmac_ptp_register(struct stmmac_priv *priv)
 {
        spin_lock_init(&priv->ptp_lock);
        priv->ptp_clock_ops = stmmac_ptp_clock_ops;
@@ -185,15 +185,10 @@ int stmmac_ptp_register(struct stmmac_priv *priv)
        priv->ptp_clock = ptp_clock_register(&priv->ptp_clock_ops,
                                             priv->device);
        if (IS_ERR(priv->ptp_clock)) {
+               netdev_err(priv->dev, "ptp_clock_register failed\n");
                priv->ptp_clock = NULL;
-               return PTR_ERR(priv->ptp_clock);
-       }
-
-       spin_lock_init(&priv->ptp_lock);
-
-       netdev_dbg(priv->dev, "Added PTP HW clock successfully\n");
-
-       return 0;
+       } else if (priv->ptp_clock)
+               netdev_info(priv->dev, "registered PTP clock\n");
 }
 
 /**
index 0d00531..5eedac4 100644 (file)
@@ -982,11 +982,13 @@ static int dwceqos_mii_probe(struct net_device *ndev)
        if (netif_msg_probe(lp))
                phy_attached_info(phydev);
 
-       phydev->supported &= PHY_GBIT_FEATURES;
+       phydev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                            SUPPORTED_Asym_Pause;
 
        lp->link    = 0;
        lp->speed   = 0;
        lp->duplex  = DUPLEX_UNKNOWN;
+       lp->flowcontrol.autoneg = AUTONEG_ENABLE;
 
        return 0;
 }
index 3c20e87..42edd7b 100644 (file)
@@ -58,9 +58,9 @@ struct geneve_dev {
        struct hlist_node  hlist;       /* vni hash table */
        struct net         *net;        /* netns for packet i/o */
        struct net_device  *dev;        /* netdev for geneve tunnel */
-       struct geneve_sock *sock4;      /* IPv4 socket used for geneve tunnel */
+       struct geneve_sock __rcu *sock4;        /* IPv4 socket used for geneve tunnel */
 #if IS_ENABLED(CONFIG_IPV6)
-       struct geneve_sock *sock6;      /* IPv6 socket used for geneve tunnel */
+       struct geneve_sock __rcu *sock6;        /* IPv6 socket used for geneve tunnel */
 #endif
        u8                 vni[3];      /* virtual network ID for tunnel */
        u8                 ttl;         /* TTL override */
@@ -453,7 +453,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
 
        skb_gro_pull(skb, gh_len);
        skb_gro_postpull_rcsum(skb, gh, gh_len);
-       pp = ptype->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
        flush = 0;
 
 out_unlock:
@@ -543,9 +543,19 @@ static void __geneve_sock_release(struct geneve_sock *gs)
 
 static void geneve_sock_release(struct geneve_dev *geneve)
 {
-       __geneve_sock_release(geneve->sock4);
+       struct geneve_sock *gs4 = rtnl_dereference(geneve->sock4);
 #if IS_ENABLED(CONFIG_IPV6)
-       __geneve_sock_release(geneve->sock6);
+       struct geneve_sock *gs6 = rtnl_dereference(geneve->sock6);
+
+       rcu_assign_pointer(geneve->sock6, NULL);
+#endif
+
+       rcu_assign_pointer(geneve->sock4, NULL);
+       synchronize_net();
+
+       __geneve_sock_release(gs4);
+#if IS_ENABLED(CONFIG_IPV6)
+       __geneve_sock_release(gs6);
 #endif
 }
 
@@ -586,10 +596,10 @@ out:
        gs->flags = geneve->flags;
 #if IS_ENABLED(CONFIG_IPV6)
        if (ipv6)
-               geneve->sock6 = gs;
+               rcu_assign_pointer(geneve->sock6, gs);
        else
 #endif
-               geneve->sock4 = gs;
+               rcu_assign_pointer(geneve->sock4, gs);
 
        hash = geneve_net_vni_hash(geneve->vni);
        hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]);
@@ -603,9 +613,7 @@ static int geneve_open(struct net_device *dev)
        bool metadata = geneve->collect_md;
        int ret = 0;
 
-       geneve->sock4 = NULL;
 #if IS_ENABLED(CONFIG_IPV6)
-       geneve->sock6 = NULL;
        if (ipv6 || metadata)
                ret = geneve_sock_add(geneve, true);
 #endif
@@ -720,6 +728,9 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb,
        struct rtable *rt = NULL;
        __u8 tos;
 
+       if (!rcu_dereference(geneve->sock4))
+               return ERR_PTR(-EIO);
+
        memset(fl4, 0, sizeof(*fl4));
        fl4->flowi4_mark = skb->mark;
        fl4->flowi4_proto = IPPROTO_UDP;
@@ -772,11 +783,15 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
 {
        bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
        struct geneve_dev *geneve = netdev_priv(dev);
-       struct geneve_sock *gs6 = geneve->sock6;
        struct dst_entry *dst = NULL;
        struct dst_cache *dst_cache;
+       struct geneve_sock *gs6;
        __u8 prio;
 
+       gs6 = rcu_dereference(geneve->sock6);
+       if (!gs6)
+               return ERR_PTR(-EIO);
+
        memset(fl6, 0, sizeof(*fl6));
        fl6->flowi6_mark = skb->mark;
        fl6->flowi6_proto = IPPROTO_UDP;
@@ -842,7 +857,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                                   struct ip_tunnel_info *info)
 {
        struct geneve_dev *geneve = netdev_priv(dev);
-       struct geneve_sock *gs4 = geneve->sock4;
+       struct geneve_sock *gs4;
        struct rtable *rt = NULL;
        const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
@@ -853,6 +868,10 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
        u32 flags = geneve->flags;
 
+       gs4 = rcu_dereference(geneve->sock4);
+       if (!gs4)
+               goto tx_error;
+
        if (geneve->collect_md) {
                if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
                        netdev_dbg(dev, "no tunnel metadata\n");
@@ -932,9 +951,9 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                                    struct ip_tunnel_info *info)
 {
        struct geneve_dev *geneve = netdev_priv(dev);
-       struct geneve_sock *gs6 = geneve->sock6;
        struct dst_entry *dst = NULL;
        const struct iphdr *iip; /* interior IP header */
+       struct geneve_sock *gs6;
        int err = -EINVAL;
        struct flowi6 fl6;
        __u8 prio, ttl;
@@ -943,6 +962,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
        u32 flags = geneve->flags;
 
+       gs6 = rcu_dereference(geneve->sock6);
+       if (!gs6)
+               goto tx_error;
+
        if (geneve->collect_md) {
                if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
                        netdev_dbg(dev, "no tunnel metadata\n");
index f0919bd..f638215 100644 (file)
@@ -447,7 +447,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
         * Setup the sendside checksum offload only if this is not a
         * GSO packet.
         */
-       if (skb_is_gso(skb)) {
+       if ((net_trans_info & (INFO_TCP | INFO_UDP)) && skb_is_gso(skb)) {
                struct ndis_tcp_lso_info *lso_info;
 
                rndis_msg_size += NDIS_LSO_PPI_SIZE;
@@ -607,15 +607,18 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
               packet->total_data_buflen);
 
        skb->protocol = eth_type_trans(skb, net);
-       if (csum_info) {
-               /* We only look at the IP checksum here.
-                * Should we be dropping the packet if checksum
-                * failed? How do we deal with other checksums - TCP/UDP?
-                */
-               if (csum_info->receive.ip_checksum_succeeded)
+
+       /* skb is already created with CHECKSUM_NONE */
+       skb_checksum_none_assert(skb);
+
+       /*
+        * In Linux, the IP checksum is always checked.
+        * Do L4 checksum offload if enabled and present.
+        */
+       if (csum_info && (net->features & NETIF_F_RXCSUM)) {
+               if (csum_info->receive.tcp_checksum_succeeded ||
+                   csum_info->receive.udp_checksum_succeeded)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
-               else
-                       skb->ip_summed = CHECKSUM_NONE;
        }
 
        if (vlan_tci & VLAN_TAG_PRESENT)
@@ -696,12 +699,8 @@ int netvsc_recv_callback(struct hv_device *device_obj,
 static void netvsc_get_drvinfo(struct net_device *net,
                               struct ethtool_drvinfo *info)
 {
-       struct net_device_context *net_device_ctx = netdev_priv(net);
-       struct hv_device *dev = net_device_ctx->device_ctx;
-
        strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
        strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
-       strlcpy(info->bus_info, vmbus_dev_name(dev), sizeof(info->bus_info));
 }
 
 static void netvsc_get_channels(struct net_device *net,
index 3ea47f2..d2e61e0 100644 (file)
@@ -397,6 +397,14 @@ static struct macsec_cb *macsec_skb_cb(struct sk_buff *skb)
 #define DEFAULT_ENCRYPT false
 #define DEFAULT_ENCODING_SA 0
 
+static bool send_sci(const struct macsec_secy *secy)
+{
+       const struct macsec_tx_sc *tx_sc = &secy->tx_sc;
+
+       return tx_sc->send_sci ||
+               (secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb);
+}
+
 static sci_t make_sci(u8 *addr, __be16 port)
 {
        sci_t sci;
@@ -437,15 +445,15 @@ static unsigned int macsec_extra_len(bool sci_present)
 
 /* Fill SecTAG according to IEEE 802.1AE-2006 10.5.3 */
 static void macsec_fill_sectag(struct macsec_eth_header *h,
-                              const struct macsec_secy *secy, u32 pn)
+                              const struct macsec_secy *secy, u32 pn,
+                              bool sci_present)
 {
        const struct macsec_tx_sc *tx_sc = &secy->tx_sc;
 
-       memset(&h->tci_an, 0, macsec_sectag_len(tx_sc->send_sci));
+       memset(&h->tci_an, 0, macsec_sectag_len(sci_present));
        h->eth.h_proto = htons(ETH_P_MACSEC);
 
-       if (tx_sc->send_sci ||
-           (secy->n_rx_sc > 1 && !tx_sc->end_station && !tx_sc->scb)) {
+       if (sci_present) {
                h->tci_an |= MACSEC_TCI_SC;
                memcpy(&h->secure_channel_id, &secy->sci,
                       sizeof(h->secure_channel_id));
@@ -650,6 +658,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
        struct macsec_tx_sc *tx_sc;
        struct macsec_tx_sa *tx_sa;
        struct macsec_dev *macsec = macsec_priv(dev);
+       bool sci_present;
        u32 pn;
 
        secy = &macsec->secy;
@@ -687,7 +696,8 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
 
        unprotected_len = skb->len;
        eth = eth_hdr(skb);
-       hh = (struct macsec_eth_header *)skb_push(skb, macsec_extra_len(tx_sc->send_sci));
+       sci_present = send_sci(secy);
+       hh = (struct macsec_eth_header *)skb_push(skb, macsec_extra_len(sci_present));
        memmove(hh, eth, 2 * ETH_ALEN);
 
        pn = tx_sa_update_pn(tx_sa, secy);
@@ -696,7 +706,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
                kfree_skb(skb);
                return ERR_PTR(-ENOLINK);
        }
-       macsec_fill_sectag(hh, secy, pn);
+       macsec_fill_sectag(hh, secy, pn, sci_present);
        macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN);
 
        skb_put(skb, secy->icv_len);
@@ -726,10 +736,10 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
        skb_to_sgvec(skb, sg, 0, skb->len);
 
        if (tx_sc->encrypt) {
-               int len = skb->len - macsec_hdr_len(tx_sc->send_sci) -
+               int len = skb->len - macsec_hdr_len(sci_present) -
                          secy->icv_len;
                aead_request_set_crypt(req, sg, sg, len, iv);
-               aead_request_set_ad(req, macsec_hdr_len(tx_sc->send_sci));
+               aead_request_set_ad(req, macsec_hdr_len(sci_present));
        } else {
                aead_request_set_crypt(req, sg, sg, 0, iv);
                aead_request_set_ad(req, skb->len - secy->icv_len);
index f279a89..a52b560 100644 (file)
 #define AT803X_MMD_ACCESS_CONTROL              0x0D
 #define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
 #define AT803X_FUNC_DATA                       0x4003
+#define AT803X_REG_CHIP_CONFIG                 0x1f
+#define AT803X_BT_BX_REG_SEL                   0x8000
 
 #define AT803X_DEBUG_ADDR                      0x1D
 #define AT803X_DEBUG_DATA                      0x1E
 
+#define AT803X_MODE_CFG_MASK                   0x0F
+#define AT803X_MODE_CFG_SGMII                  0x01
+
+#define AT803X_PSSR                    0x11    /*PHY-Specific Status Register*/
+#define AT803X_PSSR_MR_AN_COMPLETE     0x0200
+
 #define AT803X_DEBUG_REG_0                     0x00
 #define AT803X_DEBUG_RX_CLK_DLY_EN             BIT(15)
 
 #define AT803X_DEBUG_REG_5                     0x05
 #define AT803X_DEBUG_TX_CLK_DLY_EN             BIT(8)
 
-#define AT803X_REG_CHIP_CONFIG                 0x1f
-#define AT803X_BT_BX_REG_SEL                   0x8000
-
 #define ATH8030_PHY_ID 0x004dd076
 #define ATH8031_PHY_ID 0x004dd074
 #define ATH8035_PHY_ID 0x004dd072
@@ -209,7 +214,6 @@ static int at803x_suspend(struct phy_device *phydev)
 {
        int value;
        int wol_enabled;
-       int ccr;
 
        mutex_lock(&phydev->lock);
 
@@ -225,16 +229,6 @@ static int at803x_suspend(struct phy_device *phydev)
 
        phy_write(phydev, MII_BMCR, value);
 
-       if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
-               goto done;
-
-       /* also power-down SGMII interface */
-       ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
-       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
-       phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN);
-       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
-
-done:
        mutex_unlock(&phydev->lock);
 
        return 0;
@@ -243,7 +237,6 @@ done:
 static int at803x_resume(struct phy_device *phydev)
 {
        int value;
-       int ccr;
 
        mutex_lock(&phydev->lock);
 
@@ -251,17 +244,6 @@ static int at803x_resume(struct phy_device *phydev)
        value &= ~(BMCR_PDOWN | BMCR_ISOLATE);
        phy_write(phydev, MII_BMCR, value);
 
-       if (phydev->interface != PHY_INTERFACE_MODE_SGMII)
-               goto done;
-
-       /* also power-up SGMII interface */
-       ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
-       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
-       value = phy_read(phydev, MII_BMCR) & ~(BMCR_PDOWN | BMCR_ISOLATE);
-       phy_write(phydev, MII_BMCR, value);
-       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
-
-done:
        mutex_unlock(&phydev->lock);
 
        return 0;
@@ -381,6 +363,36 @@ static void at803x_link_change_notify(struct phy_device *phydev)
        }
 }
 
+static int at803x_aneg_done(struct phy_device *phydev)
+{
+       int ccr;
+
+       int aneg_done = genphy_aneg_done(phydev);
+       if (aneg_done != BMSR_ANEGCOMPLETE)
+               return aneg_done;
+
+       /*
+        * in SGMII mode, if copper side autoneg is successful,
+        * also check SGMII side autoneg result
+        */
+       ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
+       if ((ccr & AT803X_MODE_CFG_MASK) != AT803X_MODE_CFG_SGMII)
+               return aneg_done;
+
+       /* switch to SGMII/fiber page */
+       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
+
+       /* check if the SGMII link is OK. */
+       if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
+               pr_warn("803x_aneg_done: SGMII link is not ok\n");
+               aneg_done = 0;
+       }
+       /* switch back to copper page */
+       phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
+
+       return aneg_done;
+}
+
 static struct phy_driver at803x_driver[] = {
 {
        /* ATHEROS 8035 */
@@ -432,6 +444,7 @@ static struct phy_driver at803x_driver[] = {
        .flags                  = PHY_HAS_INTERRUPT,
        .config_aneg            = genphy_config_aneg,
        .read_status            = genphy_read_status,
+       .aneg_done              = at803x_aneg_done,
        .ack_interrupt          = &at803x_ack_interrupt,
        .config_intr            = &at803x_config_intr,
 } };
index 03d54c4..800b39f 100644 (file)
@@ -19,6 +19,7 @@
 #define TI_DP83848C_PHY_ID             0x20005ca0
 #define NS_DP83848C_PHY_ID             0x20005c90
 #define TLK10X_PHY_ID                  0x2000a210
+#define TI_DP83822_PHY_ID              0x2000a240
 
 /* Registers */
 #define DP83848_MICR                   0x11 /* MII Interrupt Control Register */
@@ -77,6 +78,7 @@ static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
        { TI_DP83848C_PHY_ID, 0xfffffff0 },
        { NS_DP83848C_PHY_ID, 0xfffffff0 },
        { TLK10X_PHY_ID, 0xfffffff0 },
+       { TI_DP83822_PHY_ID, 0xfffffff0 },
        { }
 };
 MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
@@ -105,6 +107,7 @@ 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(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
+       DP83848_PHY_DRIVER(TI_DP83822_PHY_ID, "TI DP83822 10/100 Mbps PHY"),
 };
 module_phy_driver(dp83848_driver);
 
index f79eb12..125cff5 100644 (file)
@@ -433,13 +433,13 @@ int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
        mutex_lock(&dev->phy_mutex);
        do {
                ret = asix_set_sw_mii(dev, 0);
-               if (ret == -ENODEV)
+               if (ret == -ENODEV || ret == -ETIMEDOUT)
                        break;
                usleep_range(1000, 1100);
                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
                                    0, 0, 1, &smsr, 0);
        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
-       if (ret == -ENODEV) {
+       if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
        }
@@ -497,13 +497,13 @@ int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc)
        mutex_lock(&dev->phy_mutex);
        do {
                ret = asix_set_sw_mii(dev, 1);
-               if (ret == -ENODEV)
+               if (ret == -ENODEV || ret == -ETIMEDOUT)
                        break;
                usleep_range(1000, 1100);
                ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
                                    0, 0, 1, &smsr, 1);
        } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
-       if (ret == -ENODEV) {
+       if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
        }
index 5662bab..3e37724 100644 (file)
@@ -151,7 +151,7 @@ kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
 
        status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr);
 
-       if (status < 0) {
+       if (status) {
                usb_set_intfdata(intf, NULL);
                usb_driver_release_interface(driver_of(intf), intf);
                return status;
index b5554f2..ef83ae3 100644 (file)
@@ -2279,6 +2279,7 @@ vmxnet3_set_mc(struct net_device *netdev)
                                        &adapter->shared->devRead.rxFilterConf;
        u8 *new_table = NULL;
        dma_addr_t new_table_pa = 0;
+       bool new_table_pa_valid = false;
        u32 new_mode = VMXNET3_RXM_UCAST;
 
        if (netdev->flags & IFF_PROMISC) {
@@ -2307,13 +2308,15 @@ vmxnet3_set_mc(struct net_device *netdev)
                                                        new_table,
                                                        sz,
                                                        PCI_DMA_TODEVICE);
+                               if (!dma_mapping_error(&adapter->pdev->dev,
+                                                      new_table_pa)) {
+                                       new_mode |= VMXNET3_RXM_MCAST;
+                                       new_table_pa_valid = true;
+                                       rxConf->mfTablePA = cpu_to_le64(
+                                                               new_table_pa);
+                               }
                        }
-
-                       if (!dma_mapping_error(&adapter->pdev->dev,
-                                              new_table_pa)) {
-                               new_mode |= VMXNET3_RXM_MCAST;
-                               rxConf->mfTablePA = cpu_to_le64(new_table_pa);
-                       } else {
+                       if (!new_table_pa_valid) {
                                netdev_info(netdev,
                                            "failed to copy mcast list, setting ALL_MULTI\n");
                                new_mode |= VMXNET3_RXM_ALL_MULTI;
@@ -2338,7 +2341,7 @@ vmxnet3_set_mc(struct net_device *netdev)
                               VMXNET3_CMD_UPDATE_MAC_FILTERS);
        spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
-       if (new_table_pa)
+       if (new_table_pa_valid)
                dma_unmap_single(&adapter->pdev->dev, new_table_pa,
                                 rxConf->mfTableLen, PCI_DMA_TODEVICE);
        kfree(new_table);
index 85c271c..820de6a 100644 (file)
@@ -956,6 +956,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
        if (skb->pkt_type == PACKET_LOOPBACK) {
                skb->dev = vrf_dev;
                skb->skb_iif = vrf_dev->ifindex;
+               IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
                skb->pkt_type = PACKET_HOST;
                goto out;
        }
@@ -996,6 +997,7 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
 {
        skb->dev = vrf_dev;
        skb->skb_iif = vrf_dev->ifindex;
+       IPCB(skb)->flags |= IPSKB_L3SLAVE;
 
        /* loopback traffic; do not push through packet taps again.
         * Reset pkt_type for upper layers to process skb
index e7d1668..f3c2fa3 100644 (file)
@@ -583,7 +583,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk,
                }
        }
 
-       pp = eth_gro_receive(head, skb);
+       pp = call_gro_receive(eth_gro_receive, head, skb);
        flush = 0;
 
 out:
@@ -943,17 +943,20 @@ static bool vxlan_snoop(struct net_device *dev,
 static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
 {
        struct vxlan_dev *vxlan;
+       struct vxlan_sock *sock4;
+       struct vxlan_sock *sock6 = NULL;
        unsigned short family = dev->default_dst.remote_ip.sa.sa_family;
 
+       sock4 = rtnl_dereference(dev->vn4_sock);
+
        /* The vxlan_sock is only used by dev, leaving group has
         * no effect on other vxlan devices.
         */
-       if (family == AF_INET && dev->vn4_sock &&
-           atomic_read(&dev->vn4_sock->refcnt) == 1)
+       if (family == AF_INET && sock4 && atomic_read(&sock4->refcnt) == 1)
                return false;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (family == AF_INET6 && dev->vn6_sock &&
-           atomic_read(&dev->vn6_sock->refcnt) == 1)
+       sock6 = rtnl_dereference(dev->vn6_sock);
+       if (family == AF_INET6 && sock6 && atomic_read(&sock6->refcnt) == 1)
                return false;
 #endif
 
@@ -961,10 +964,12 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
                if (!netif_running(vxlan->dev) || vxlan == dev)
                        continue;
 
-               if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock)
+               if (family == AF_INET &&
+                   rtnl_dereference(vxlan->vn4_sock) != sock4)
                        continue;
 #if IS_ENABLED(CONFIG_IPV6)
-               if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock)
+               if (family == AF_INET6 &&
+                   rtnl_dereference(vxlan->vn6_sock) != sock6)
                        continue;
 #endif
 
@@ -1005,22 +1010,25 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
 
 static void vxlan_sock_release(struct vxlan_dev *vxlan)
 {
-       bool ipv4 = __vxlan_sock_release_prep(vxlan->vn4_sock);
+       struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
 #if IS_ENABLED(CONFIG_IPV6)
-       bool ipv6 = __vxlan_sock_release_prep(vxlan->vn6_sock);
+       struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
+
+       rcu_assign_pointer(vxlan->vn6_sock, NULL);
 #endif
 
+       rcu_assign_pointer(vxlan->vn4_sock, NULL);
        synchronize_net();
 
-       if (ipv4) {
-               udp_tunnel_sock_release(vxlan->vn4_sock->sock);
-               kfree(vxlan->vn4_sock);
+       if (__vxlan_sock_release_prep(sock4)) {
+               udp_tunnel_sock_release(sock4->sock);
+               kfree(sock4);
        }
 
 #if IS_ENABLED(CONFIG_IPV6)
-       if (ipv6) {
-               udp_tunnel_sock_release(vxlan->vn6_sock->sock);
-               kfree(vxlan->vn6_sock);
+       if (__vxlan_sock_release_prep(sock6)) {
+               udp_tunnel_sock_release(sock6->sock);
+               kfree(sock6);
        }
 #endif
 }
@@ -1036,18 +1044,21 @@ static int vxlan_igmp_join(struct vxlan_dev *vxlan)
        int ret = -EINVAL;
 
        if (ip->sa.sa_family == AF_INET) {
+               struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
                struct ip_mreqn mreq = {
                        .imr_multiaddr.s_addr   = ip->sin.sin_addr.s_addr,
                        .imr_ifindex            = ifindex,
                };
 
-               sk = vxlan->vn4_sock->sock->sk;
+               sk = sock4->sock->sk;
                lock_sock(sk);
                ret = ip_mc_join_group(sk, &mreq);
                release_sock(sk);
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
-               sk = vxlan->vn6_sock->sock->sk;
+               struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
+
+               sk = sock6->sock->sk;
                lock_sock(sk);
                ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex,
                                                   &ip->sin6.sin6_addr);
@@ -1067,18 +1078,21 @@ static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
        int ret = -EINVAL;
 
        if (ip->sa.sa_family == AF_INET) {
+               struct vxlan_sock *sock4 = rtnl_dereference(vxlan->vn4_sock);
                struct ip_mreqn mreq = {
                        .imr_multiaddr.s_addr   = ip->sin.sin_addr.s_addr,
                        .imr_ifindex            = ifindex,
                };
 
-               sk = vxlan->vn4_sock->sock->sk;
+               sk = sock4->sock->sk;
                lock_sock(sk);
                ret = ip_mc_leave_group(sk, &mreq);
                release_sock(sk);
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
-               sk = vxlan->vn6_sock->sock->sk;
+               struct vxlan_sock *sock6 = rtnl_dereference(vxlan->vn6_sock);
+
+               sk = sock6->sock->sk;
                lock_sock(sk);
                ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex,
                                                   &ip->sin6.sin6_addr);
@@ -1828,11 +1842,15 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
                                          struct dst_cache *dst_cache,
                                          const struct ip_tunnel_info *info)
 {
+       struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
        bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
        struct dst_entry *ndst;
        struct flowi6 fl6;
        int err;
 
+       if (!sock6)
+               return ERR_PTR(-EIO);
+
        if (tos && !info)
                use_cache = false;
        if (use_cache) {
@@ -1850,7 +1868,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
        fl6.flowi6_proto = IPPROTO_UDP;
 
        err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
-                                        vxlan->vn6_sock->sock->sk,
+                                        sock6->sock->sk,
                                         &ndst, &fl6);
        if (err < 0)
                return ERR_PTR(err);
@@ -1995,9 +2013,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
        }
 
        if (dst->sa.sa_family == AF_INET) {
-               if (!vxlan->vn4_sock)
+               struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
+
+               if (!sock4)
                        goto drop;
-               sk = vxlan->vn4_sock->sock->sk;
+               sk = sock4->sock->sk;
 
                rt = vxlan_get_route(vxlan, skb,
                                     rdst ? rdst->remote_ifindex : 0, tos,
@@ -2050,12 +2070,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                    src_port, dst_port, xnet, !udp_sum);
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
+               struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
                struct dst_entry *ndst;
                u32 rt6i_flags;
 
-               if (!vxlan->vn6_sock)
+               if (!sock6)
                        goto drop;
-               sk = vxlan->vn6_sock->sock->sk;
+               sk = sock6->sock->sk;
 
                ndst = vxlan6_get_route(vxlan, skb,
                                        rdst ? rdst->remote_ifindex : 0, tos,
@@ -2415,9 +2436,10 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
 
        if (ip_tunnel_info_af(info) == AF_INET) {
+               struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
                struct rtable *rt;
 
-               if (!vxlan->vn4_sock)
+               if (!sock4)
                        return -EINVAL;
                rt = vxlan_get_route(vxlan, skb, 0, info->key.tos,
                                     info->key.u.ipv4.dst,
@@ -2429,8 +2451,6 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 #if IS_ENABLED(CONFIG_IPV6)
                struct dst_entry *ndst;
 
-               if (!vxlan->vn6_sock)
-                       return -EINVAL;
                ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos,
                                        info->key.label, &info->key.u.ipv6.dst,
                                        &info->key.u.ipv6.src, NULL, info);
@@ -2740,10 +2760,10 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
                return PTR_ERR(vs);
 #if IS_ENABLED(CONFIG_IPV6)
        if (ipv6)
-               vxlan->vn6_sock = vs;
+               rcu_assign_pointer(vxlan->vn6_sock, vs);
        else
 #endif
-               vxlan->vn4_sock = vs;
+               rcu_assign_pointer(vxlan->vn4_sock, vs);
        vxlan_vs_add_dev(vs, vxlan);
        return 0;
 }
@@ -2754,9 +2774,9 @@ static int vxlan_sock_add(struct vxlan_dev *vxlan)
        bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA;
        int ret = 0;
 
-       vxlan->vn4_sock = NULL;
+       RCU_INIT_POINTER(vxlan->vn4_sock, NULL);
 #if IS_ENABLED(CONFIG_IPV6)
-       vxlan->vn6_sock = NULL;
+       RCU_INIT_POINTER(vxlan->vn6_sock, NULL);
        if (ipv6 || metadata)
                ret = __vxlan_sock_add(vxlan, true);
 #endif
index 33ab334..4e9fe75 100644 (file)
@@ -294,7 +294,7 @@ config FSL_UCC_HDLC
 config SLIC_DS26522
        tristate "Slic Maxim ds26522 card support"
        depends on SPI
-       depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE
+       depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST
        help
          This module initializes and configures the slic maxim card
          in T1 or E1 mode.
index d06a887..b776a0a 100644 (file)
@@ -223,12 +223,19 @@ static int slic_ds26522_probe(struct spi_device *spi)
        return ret;
 }
 
+static const struct spi_device_id slic_ds26522_id[] = {
+       { .name = "ds26522" },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(spi, slic_ds26522_id);
+
 static const struct of_device_id slic_ds26522_match[] = {
        {
         .compatible = "maxim,ds26522",
         },
        {},
 };
+MODULE_DEVICE_TABLE(of, slic_ds26522_match);
 
 static struct spi_driver slic_ds26522_driver = {
        .driver = {
@@ -239,6 +246,7 @@ static struct spi_driver slic_ds26522_driver = {
                   },
        .probe = slic_ds26522_probe,
        .remove = slic_ds26522_remove,
+       .id_table = slic_ds26522_id,
 };
 
 static int __init slic_ds26522_init(void)
index dda49af..521f1c5 100644 (file)
@@ -450,6 +450,7 @@ struct ath10k_debug {
        u32 pktlog_filter;
        u32 reg_addr;
        u32 nf_cal_period;
+       void *cal_data;
 
        struct ath10k_fw_crash_data *fw_crash_data;
 };
index 832da6e..82a4c67 100644 (file)
@@ -30,6 +30,8 @@
 /* ms */
 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
 
+#define ATH10K_DEBUG_CAL_DATA_LEN 12064
+
 #define ATH10K_FW_CRASH_DUMP_VERSION 1
 
 /**
@@ -1451,56 +1453,51 @@ static const struct file_operations fops_fw_dbglog = {
        .llseek = default_llseek,
 };
 
-static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
+static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
 {
-       struct ath10k *ar = inode->i_private;
-       void *buf;
        u32 hi_addr;
        __le32 addr;
        int ret;
 
-       mutex_lock(&ar->conf_mutex);
-
-       if (ar->state != ATH10K_STATE_ON &&
-           ar->state != ATH10K_STATE_UTF) {
-               ret = -ENETDOWN;
-               goto err;
-       }
+       lockdep_assert_held(&ar->conf_mutex);
 
-       buf = vmalloc(ar->hw_params.cal_data_len);
-       if (!buf) {
-               ret = -ENOMEM;
-               goto err;
-       }
+       if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN))
+               return -EINVAL;
 
        hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
 
        ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
        if (ret) {
-               ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
-               goto err_vfree;
+               ath10k_warn(ar, "failed to read hi_board_data address: %d\n",
+                           ret);
+               return ret;
        }
 
-       ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
+       ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), ar->debug.cal_data,
                                   ar->hw_params.cal_data_len);
        if (ret) {
                ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
-               goto err_vfree;
+               return ret;
        }
 
-       file->private_data = buf;
+       return 0;
+}
 
-       mutex_unlock(&ar->conf_mutex);
+static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
+{
+       struct ath10k *ar = inode->i_private;
 
-       return 0;
+       mutex_lock(&ar->conf_mutex);
 
-err_vfree:
-       vfree(buf);
+       if (ar->state == ATH10K_STATE_ON ||
+           ar->state == ATH10K_STATE_UTF) {
+               ath10k_debug_cal_data_fetch(ar);
+       }
 
-err:
+       file->private_data = ar;
        mutex_unlock(&ar->conf_mutex);
 
-       return ret;
+       return 0;
 }
 
 static ssize_t ath10k_debug_cal_data_read(struct file *file,
@@ -1508,18 +1505,16 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file,
                                          size_t count, loff_t *ppos)
 {
        struct ath10k *ar = file->private_data;
-       void *buf = file->private_data;
 
-       return simple_read_from_buffer(user_buf, count, ppos,
-                                      buf, ar->hw_params.cal_data_len);
-}
+       mutex_lock(&ar->conf_mutex);
 
-static int ath10k_debug_cal_data_release(struct inode *inode,
-                                        struct file *file)
-{
-       vfree(file->private_data);
+       count = simple_read_from_buffer(user_buf, count, ppos,
+                                       ar->debug.cal_data,
+                                       ar->hw_params.cal_data_len);
 
-       return 0;
+       mutex_unlock(&ar->conf_mutex);
+
+       return count;
 }
 
 static ssize_t ath10k_write_ani_enable(struct file *file,
@@ -1580,7 +1575,6 @@ static const struct file_operations fops_ani_enable = {
 static const struct file_operations fops_cal_data = {
        .open = ath10k_debug_cal_data_open,
        .read = ath10k_debug_cal_data_read,
-       .release = ath10k_debug_cal_data_release,
        .owner = THIS_MODULE,
        .llseek = default_llseek,
 };
@@ -1932,6 +1926,8 @@ void ath10k_debug_stop(struct ath10k *ar)
 {
        lockdep_assert_held(&ar->conf_mutex);
 
+       ath10k_debug_cal_data_fetch(ar);
+
        /* Must not use _sync to avoid deadlock, we do that in
         * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
         * warning from del_timer(). */
@@ -2344,6 +2340,10 @@ int ath10k_debug_create(struct ath10k *ar)
        if (!ar->debug.fw_crash_data)
                return -ENOMEM;
 
+       ar->debug.cal_data = vzalloc(ATH10K_DEBUG_CAL_DATA_LEN);
+       if (!ar->debug.cal_data)
+               return -ENOMEM;
+
        INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
        INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
        INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
@@ -2357,6 +2357,9 @@ void ath10k_debug_destroy(struct ath10k *ar)
        vfree(ar->debug.fw_crash_data);
        ar->debug.fw_crash_data = NULL;
 
+       vfree(ar->debug.cal_data);
+       ar->debug.cal_data = NULL;
+
        ath10k_debug_fw_stats_reset(ar);
 
        kfree(ar->debug.tpc_stats);
index eab0ab9..76eb336 100644 (file)
@@ -1401,6 +1401,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = {
        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0))},
        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1))},
        {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x2))},
+       {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x18))},
        {},
 };
 
index b6f064a..7e27a06 100644 (file)
@@ -33,7 +33,6 @@ struct coeff {
 
 enum ar9003_cal_types {
        IQ_MISMATCH_CAL = BIT(0),
-       TEMP_COMP_CAL = BIT(1),
 };
 
 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
@@ -59,12 +58,6 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
                /* Kick-off cal */
                REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
                break;
-       case TEMP_COMP_CAL:
-               ath_dbg(common, CALIBRATE,
-                       "starting Temperature Compensation Calibration\n");
-               REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_LOCAL);
-               REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_START);
-               break;
        default:
                ath_err(common, "Invalid calibration type\n");
                break;
@@ -93,8 +86,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
                /*
                * Accumulate cal measures for active chains
                */
-               if (cur_caldata->calCollect)
-                       cur_caldata->calCollect(ah);
+               cur_caldata->calCollect(ah);
                ah->cal_samples++;
 
                if (ah->cal_samples >= cur_caldata->calNumSamples) {
@@ -107,8 +99,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
                        /*
                        * Process accumulated data
                        */
-                       if (cur_caldata->calPostProc)
-                               cur_caldata->calPostProc(ah, numChains);
+                       cur_caldata->calPostProc(ah, numChains);
 
                        /* Calibration has finished. */
                        caldata->CalValid |= cur_caldata->calType;
@@ -323,16 +314,9 @@ static const struct ath9k_percal_data iq_cal_single_sample = {
        ar9003_hw_iqcalibrate
 };
 
-static const struct ath9k_percal_data temp_cal_single_sample = {
-       TEMP_COMP_CAL,
-       MIN_CAL_SAMPLES,
-       PER_MAX_LOG_COUNT,
-};
-
 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
 {
        ah->iq_caldata.calData = &iq_cal_single_sample;
-       ah->temp_caldata.calData = &temp_cal_single_sample;
 
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                ah->enabled_cals |= TX_IQ_CAL;
@@ -340,7 +324,7 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
                        ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
        }
 
-       ah->supp_cals = IQ_MISMATCH_CAL | TEMP_COMP_CAL;
+       ah->supp_cals = IQ_MISMATCH_CAL;
 }
 
 #define OFF_UPPER_LT 24
@@ -1399,9 +1383,6 @@ static void ar9003_hw_init_cal_common(struct ath_hw *ah)
        INIT_CAL(&ah->iq_caldata);
        INSERT_CAL(ah, &ah->iq_caldata);
 
-       INIT_CAL(&ah->temp_caldata);
-       INSERT_CAL(ah, &ah->temp_caldata);
-
        /* Initialize current pointer to first element in list */
        ah->cal_list_curr = ah->cal_list;
 
index 2a5d3ad..9cbca12 100644 (file)
@@ -830,7 +830,6 @@ struct ath_hw {
        /* Calibration */
        u32 supp_cals;
        struct ath9k_cal_list iq_caldata;
-       struct ath9k_cal_list temp_caldata;
        struct ath9k_cal_list adcgain_caldata;
        struct ath9k_cal_list adcdc_caldata;
        struct ath9k_cal_list *cal_list;
index 9448012..274dd5a 100644 (file)
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
                skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
 
                ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-                                        priv->wdev.iftype, 0, false);
+                                        priv->wdev.iftype, 0, NULL, NULL);
 
                while (!skb_queue_empty(&list)) {
                        struct rx_packet_hdr *rx_hdr;
index 1016628..08d587a 100644 (file)
@@ -238,7 +238,7 @@ struct rtl8xxxu_rxdesc16 {
        u32 pattern1match:1;
        u32 pattern0match:1;
 #endif
-       __le32 tsfl;
+       u32 tsfl;
 #if 0
        u32 bassn:12;
        u32 bavld:1;
@@ -368,7 +368,7 @@ struct rtl8xxxu_rxdesc24 {
        u32 ldcp:1;
        u32 splcp:1;
 #endif
-       __le32 tsfl;
+       u32 tsfl;
 };
 
 struct rtl8xxxu_txdesc32 {
index df54d27..a793fed 100644 (file)
@@ -1461,7 +1461,9 @@ static int rtl8192eu_active_to_emu(struct rtl8xxxu_priv *priv)
        int count, ret = 0;
 
        /* Turn off RF */
-       rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
+       val8 = rtl8xxxu_read8(priv, REG_RF_CTRL);
+       val8 &= ~RF_ENABLE;
+       rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
 
        /* Switch DPDT_SEL_P output from register 0x65[2] */
        val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
@@ -1593,6 +1595,10 @@ static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
        u32 val32;
        u8 val8;
 
+       val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA);
+       val32 |= (BIT(22) | BIT(23));
+       rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val32);
+
        val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG);
        val8 |= BIT(5);
        rtl8xxxu_write8(priv, REG_GPIO_MUXCFG, val8);
index 6c086b5..02b8ddd 100644 (file)
@@ -1498,6 +1498,10 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv)
        u32 val32;
        u8 val8;
 
+       val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA);
+       val32 |= (BIT(22) | BIT(23));
+       rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val32);
+
        /*
         * No indication anywhere as to what 0x0790 does. The 2 antenna
         * vendor code preserves bits 6-7 here.
index b2d7f6e..a5e6ec2 100644 (file)
@@ -5197,7 +5197,12 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
                pkt_offset = roundup(pkt_len + drvinfo_sz + desc_shift +
                                     sizeof(struct rtl8xxxu_rxdesc16), 128);
 
-               if (pkt_cnt > 1)
+               /*
+                * Only clone the skb if there's enough data at the end to
+                * at least cover the rx descriptor
+                */
+               if (pkt_cnt > 1 &&
+                   urb_len > (pkt_offset + sizeof(struct rtl8xxxu_rxdesc16)))
                        next_skb = skb_clone(skb, GFP_ATOMIC);
 
                rx_status = IEEE80211_SKB_RXCB(skb);
@@ -5215,7 +5220,7 @@ int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
                        rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats,
                                                   rx_desc->rxmcs);
 
-               rx_status->mactime = le32_to_cpu(rx_desc->tsfl);
+               rx_status->mactime = rx_desc->tsfl;
                rx_status->flag |= RX_FLAG_MACTIME_START;
 
                if (!rx_desc->swdec)
@@ -5285,7 +5290,7 @@ int rtl8xxxu_parse_rxdesc24(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
                rtl8xxxu_rx_parse_phystats(priv, rx_status, phy_stats,
                                           rx_desc->rxmcs);
 
-       rx_status->mactime = le32_to_cpu(rx_desc->tsfl);
+       rx_status->mactime = rx_desc->tsfl;
        rx_status->flag |= RX_FLAG_MACTIME_START;
 
        if (!rx_desc->swdec)
index f95760c..8e7f23c 100644 (file)
@@ -111,7 +111,7 @@ static void rtl_fw_do_work(const struct firmware *firmware, void *context,
                        if (!err)
                                goto found_alt;
                }
-               pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
+               pr_err("Selected firmware is not available\n");
                rtlpriv->max_fw_size = 0;
                return;
        }
index e7b11b4..f361808 100644 (file)
@@ -86,6 +86,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        u8 tid;
+       char *fw_name;
 
        rtl8188ee_bt_reg_init(hw);
        rtlpriv->dm.dm_initialgain_enable = 1;
@@ -169,10 +170,10 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
                return 1;
        }
 
-       rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin";
+       fw_name = "rtlwifi/rtl8188efw.bin";
        rtlpriv->max_fw_size = 0x8000;
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -284,7 +285,6 @@ static const struct rtl_hal_cfg rtl88ee_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl88e_pci",
-       .fw_name = "rtlwifi/rtl8188efw.bin",
        .ops = &rtl8188ee_hal_ops,
        .mod_params = &rtl88ee_mod_params,
 
index 87aa209..8b6e37c 100644 (file)
@@ -96,6 +96,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";
 
        rtl8192ce_bt_reg_init(hw);
 
@@ -167,15 +168,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
        }
 
        /* request fw */
-       if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
-           !IS_92C_SERIAL(rtlhal->version))
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
-       else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+       if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
+               fw_name = "rtlwifi/rtl8192cfwU_B.bin";
 
        rtlpriv->max_fw_size = 0x4000;
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -262,7 +260,6 @@ static const struct rtl_hal_cfg rtl92ce_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl92c_pci",
-       .fw_name = "rtlwifi/rtl8192cfw.bin",
        .ops = &rtl8192ce_hal_ops,
        .mod_params = &rtl92ce_mod_params,
 
index 7c6f7f0..f953320 100644 (file)
@@ -59,6 +59,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        int err;
+       char *fw_name;
 
        rtlpriv->dm.dm_initialgain_enable = true;
        rtlpriv->dm.dm_flag = 0;
@@ -77,18 +78,18 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
        }
        if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) &&
            !IS_92C_SERIAL(rtlpriv->rtlhal.version)) {
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin";
+               fw_name = "rtlwifi/rtl8192cufw_A.bin";
        } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) {
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin";
+               fw_name = "rtlwifi/rtl8192cufw_B.bin";
        } else {
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
+               fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
        }
        /* provide name of alternative file */
        rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin";
-       pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
+       pr_info("Loading firmware %s\n", fw_name);
        rtlpriv->max_fw_size = 0x4000;
        err = request_firmware_nowait(THIS_MODULE, 1,
-                                     rtlpriv->cfg->fw_name, rtlpriv->io.dev,
+                                     fw_name, rtlpriv->io.dev,
                                      GFP_KERNEL, hw, rtl_fw_cb);
        return err;
 }
@@ -187,7 +188,6 @@ static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
 
 static struct rtl_hal_cfg rtl92cu_hal_cfg = {
        .name = "rtl92c_usb",
-       .fw_name = "rtlwifi/rtl8192cufw.bin",
        .ops = &rtl8192cu_hal_ops,
        .mod_params = &rtl92cu_mod_params,
        .usb_interface_cfg = &rtl92cu_interface_cfg,
index 0538a4d..1ebfee1 100644 (file)
@@ -92,6 +92,7 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
        u8 tid;
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       char *fw_name = "rtlwifi/rtl8192defw.bin";
 
        rtlpriv->dm.dm_initialgain_enable = true;
        rtlpriv->dm.dm_flag = 0;
@@ -181,10 +182,10 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
 
        rtlpriv->max_fw_size = 0x8000;
        pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
-       pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
+       pr_info("Loading firmware file %s\n", fw_name);
 
        /* request fw */
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -266,7 +267,6 @@ static const struct rtl_hal_cfg rtl92de_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl8192de",
-       .fw_name = "rtlwifi/rtl8192defw.bin",
        .ops = &rtl8192de_hal_ops,
        .mod_params = &rtl92de_mod_params,
 
index ac299cb..46b605d 100644 (file)
@@ -91,6 +91,7 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        int err = 0;
+       char *fw_name;
 
        rtl92ee_bt_reg_init(hw);
        rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
@@ -170,11 +171,11 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
        }
 
        /* request fw */
-       rtlpriv->cfg->fw_name = "rtlwifi/rtl8192eefw.bin";
+       fw_name = "rtlwifi/rtl8192eefw.bin";
 
        rtlpriv->max_fw_size = 0x8000;
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -266,7 +267,6 @@ static const struct rtl_hal_cfg rtl92ee_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl92ee_pci",
-       .fw_name = "rtlwifi/rtl8192eefw.bin",
        .ops = &rtl8192ee_hal_ops,
        .mod_params = &rtl92ee_mod_params,
 
index 5e8e02d..3e1eaea 100644 (file)
@@ -89,12 +89,13 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
        struct ieee80211_hw *hw = context;
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rt_firmware *pfirmware = NULL;
+       char *fw_name = "rtlwifi/rtl8192sefw.bin";
 
        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
                         "Firmware callback routine entered!\n");
        complete(&rtlpriv->firmware_loading_complete);
        if (!firmware) {
-               pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
+               pr_err("Firmware %s not available\n", fw_name);
                rtlpriv->max_fw_size = 0;
                return;
        }
@@ -117,6 +118,7 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        int err = 0;
        u16 earlyrxthreshold = 7;
+       char *fw_name = "rtlwifi/rtl8192sefw.bin";
 
        rtlpriv->dm.dm_initialgain_enable = true;
        rtlpriv->dm.dm_flag = 0;
@@ -214,9 +216,9 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
                               sizeof(struct fw_hdr);
        pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
-               "Loading firmware %s\n", rtlpriv->cfg->fw_name);
+               "Loading firmware %s\n", fw_name);
        /* request fw */
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl92se_fw_cb);
        if (err) {
@@ -310,7 +312,6 @@ static const struct rtl_hal_cfg rtl92se_hal_cfg = {
        .bar_id = 1,
        .write_readback = false,
        .name = "rtl92s_pci",
-       .fw_name = "rtlwifi/rtl8192sefw.bin",
        .ops = &rtl8192se_hal_ops,
        .mod_params = &rtl92se_mod_params,
 
index 89c828a..c51a9e8 100644 (file)
@@ -94,6 +94,7 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        int err = 0;
+       char *fw_name = "rtlwifi/rtl8723fw.bin";
 
        rtl8723e_bt_reg_init(hw);
 
@@ -176,14 +177,12 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
                return 1;
        }
 
-       if (IS_VENDOR_8723_A_CUT(rtlhal->version))
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin";
-       else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin";
+       if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+               fw_name = "rtlwifi/rtl8723fw_B.bin";
 
        rtlpriv->max_fw_size = 0x6000;
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -280,7 +279,6 @@ static const struct rtl_hal_cfg rtl8723e_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl8723e_pci",
-       .fw_name = "rtlwifi/rtl8723efw.bin",
        .ops = &rtl8723e_hal_ops,
        .mod_params = &rtl8723e_mod_params,
        .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
index 20b53f0..847644d 100644 (file)
@@ -91,6 +91,7 @@ int rtl8723be_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_mac *mac = rtl_mac(rtl_priv(hw));
+       char *fw_name = "rtlwifi/rtl8723befw.bin";
 
        rtl8723be_bt_reg_init(hw);
        rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
@@ -184,8 +185,8 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
        }
 
        rtlpriv->max_fw_size = 0x8000;
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -280,7 +281,6 @@ static const struct rtl_hal_cfg rtl8723be_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl8723be_pci",
-       .fw_name = "rtlwifi/rtl8723befw.bin",
        .ops = &rtl8723be_hal_ops,
        .mod_params = &rtl8723be_mod_params,
        .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
index 22f687b..297938e 100644 (file)
@@ -93,6 +93,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       char *fw_name, *wowlan_fw_name;
 
        rtl8821ae_bt_reg_init(hw);
        rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
@@ -203,17 +204,17 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
        }
 
        if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8812aefw.bin";
-               rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin";
+               fw_name = "rtlwifi/rtl8812aefw.bin";
+               wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin";
        } else {
-               rtlpriv->cfg->fw_name = "rtlwifi/rtl8821aefw.bin";
-               rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin";
+               fw_name = "rtlwifi/rtl8821aefw.bin";
+               wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin";
        }
 
        rtlpriv->max_fw_size = 0x8000;
        /*load normal firmware*/
-       pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
-       err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
+       pr_info("Using firmware %s\n", fw_name);
+       err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_fw_cb);
        if (err) {
@@ -222,9 +223,9 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
                return 1;
        }
        /*load wowlan firmware*/
-       pr_info("Using firmware %s\n", rtlpriv->cfg->wowlan_fw_name);
+       pr_info("Using firmware %s\n", wowlan_fw_name);
        err = request_firmware_nowait(THIS_MODULE, 1,
-                                     rtlpriv->cfg->wowlan_fw_name,
+                                     wowlan_fw_name,
                                      rtlpriv->io.dev, GFP_KERNEL, hw,
                                      rtl_wowlan_fw_cb);
        if (err) {
@@ -320,7 +321,6 @@ static const struct rtl_hal_cfg rtl8821ae_hal_cfg = {
        .bar_id = 2,
        .write_readback = true,
        .name = "rtl8821ae_pci",
-       .fw_name = "rtlwifi/rtl8821aefw.bin",
        .ops = &rtl8821ae_hal_ops,
        .mod_params = &rtl8821ae_mod_params,
        .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
index 595f7d5..dafe486 100644 (file)
@@ -2278,9 +2278,7 @@ struct rtl_hal_cfg {
        u8 bar_id;
        bool write_readback;
        char *name;
-       char *fw_name;
        char *alt_fw_name;
-       char *wowlan_fw_name;
        struct rtl_hal_ops *ops;
        struct rtl_mod_params *mod_params;
        struct rtl_hal_usbint_cfg *usb_interface_cfg;
index a6e94b1..47fe7f9 100644 (file)
@@ -391,7 +391,6 @@ static void wl1271_remove(struct sdio_func *func)
        pm_runtime_get_noresume(&func->dev);
 
        platform_device_unregister(glue->core);
-       kfree(glue);
 }
 
 #ifdef CONFIG_PM
index 8b2b740..124c243 100644 (file)
@@ -89,7 +89,7 @@ config NVDIMM_PFN
          Select Y if unsure
 
 config NVDIMM_DAX
-       tristate "NVDIMM DAX: Raw access to persistent memory"
+       bool "NVDIMM DAX: Raw access to persistent memory"
        default LIBNVDIMM
        depends on NVDIMM_PFN
        help
index 3509cff..abe5c6b 100644 (file)
@@ -2176,12 +2176,14 @@ static struct device **scan_labels(struct nd_region *nd_region)
        return devs;
 
  err:
-       for (i = 0; devs[i]; i++)
-               if (is_nd_blk(&nd_region->dev))
-                       namespace_blk_release(devs[i]);
-               else
-                       namespace_pmem_release(devs[i]);
-       kfree(devs);
+       if (devs) {
+               for (i = 0; devs[i]; i++)
+                       if (is_nd_blk(&nd_region->dev))
+                               namespace_blk_release(devs[i]);
+                       else
+                               namespace_pmem_release(devs[i]);
+               kfree(devs);
+       }
        return NULL;
 }
 
index 42b3a82..2461843 100644 (file)
@@ -47,7 +47,7 @@ static struct nd_region *to_region(struct pmem_device *pmem)
        return to_nd_region(to_dev(pmem)->parent);
 }
 
-static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
+static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
                unsigned int len)
 {
        struct device *dev = to_dev(pmem);
@@ -62,8 +62,12 @@ static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
                                __func__, (unsigned long long) sector,
                                cleared / 512, cleared / 512 > 1 ? "s" : "");
                badblocks_clear(&pmem->bb, sector, cleared / 512);
+       } else {
+               return -EIO;
        }
+
        invalidate_pmem(pmem->virt_addr + offset, len);
+       return 0;
 }
 
 static void write_pmem(void *pmem_addr, struct page *page,
@@ -123,7 +127,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
                flush_dcache_page(page);
                write_pmem(pmem_addr, page, off, len);
                if (unlikely(bad_pmem)) {
-                       pmem_clear_poison(pmem, pmem_off, len);
+                       rc = pmem_clear_poison(pmem, pmem_off, len);
                        write_pmem(pmem_addr, page, off, len);
                }
        }
index 329381a..79e679d 100644 (file)
@@ -554,7 +554,7 @@ int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
 
        /* gcc-4.4.4 (at least) has issues with initializers and anon unions */
        c.identify.opcode = nvme_admin_identify;
-       c.identify.cns = cpu_to_le32(1);
+       c.identify.cns = cpu_to_le32(NVME_ID_CNS_CTRL);
 
        *id = kmalloc(sizeof(struct nvme_id_ctrl), GFP_KERNEL);
        if (!*id)
@@ -572,7 +572,7 @@ static int nvme_identify_ns_list(struct nvme_ctrl *dev, unsigned nsid, __le32 *n
        struct nvme_command c = { };
 
        c.identify.opcode = nvme_admin_identify;
-       c.identify.cns = cpu_to_le32(2);
+       c.identify.cns = cpu_to_le32(NVME_ID_CNS_NS_ACTIVE_LIST);
        c.identify.nsid = cpu_to_le32(nsid);
        return nvme_submit_sync_cmd(dev->admin_q, &c, ns_list, 0x1000);
 }
@@ -900,9 +900,9 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
                return -ENODEV;
        }
 
-       if (ns->ctrl->vs >= NVME_VS(1, 1))
+       if (ns->ctrl->vs >= NVME_VS(1, 1, 0))
                memcpy(ns->eui, (*id)->eui64, sizeof(ns->eui));
-       if (ns->ctrl->vs >= NVME_VS(1, 2))
+       if (ns->ctrl->vs >= NVME_VS(1, 2, 0))
                memcpy(ns->uuid, (*id)->nguid, sizeof(ns->uuid));
 
        return 0;
@@ -1086,6 +1086,8 @@ static int nvme_wait_ready(struct nvme_ctrl *ctrl, u64 cap, bool enabled)
        int ret;
 
        while ((ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CSTS, &csts)) == 0) {
+               if (csts == ~0)
+                       return -ENODEV;
                if ((csts & NVME_CSTS_RDY) == bit)
                        break;
 
@@ -1240,7 +1242,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        }
        page_shift = NVME_CAP_MPSMIN(cap) + 12;
 
-       if (ctrl->vs >= NVME_VS(1, 1))
+       if (ctrl->vs >= NVME_VS(1, 1, 0))
                ctrl->subsystem = NVME_CAP_NSSRC(cap);
 
        ret = nvme_identify_ctrl(ctrl, &id);
@@ -1840,7 +1842,7 @@ static void nvme_scan_work(struct work_struct *work)
                return;
 
        nn = le32_to_cpu(id->nn);
-       if (ctrl->vs >= NVME_VS(1, 1) &&
+       if (ctrl->vs >= NVME_VS(1, 1, 0) &&
            !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
                if (!nvme_scan_ns_list(ctrl, nn))
                        goto done;
index 0fc99f0..0248d0e 100644 (file)
@@ -99,6 +99,7 @@ struct nvme_dev {
        dma_addr_t cmb_dma_addr;
        u64 cmb_size;
        u32 cmbsz;
+       u32 cmbloc;
        struct nvme_ctrl ctrl;
        struct completion ioq_wait;
 };
@@ -893,7 +894,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
                         "I/O %d QID %d timeout, reset controller\n",
                         req->tag, nvmeq->qid);
                nvme_dev_disable(dev, false);
-               queue_work(nvme_workq, &dev->reset_work);
+               nvme_reset(dev);
 
                /*
                 * Mark the request as handled, since the inline shutdown
@@ -1214,7 +1215,7 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
        u64 cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
        struct nvme_queue *nvmeq;
 
-       dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1) ?
+       dev->subsystem = readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 1, 0) ?
                                                NVME_CAP_NSSRC(cap) : 0;
 
        if (dev->subsystem &&
@@ -1291,7 +1292,7 @@ static void nvme_watchdog_timer(unsigned long data)
 
        /* Skip controllers under certain specific conditions. */
        if (nvme_should_reset(dev, csts)) {
-               if (queue_work(nvme_workq, &dev->reset_work))
+               if (!nvme_reset(dev))
                        dev_warn(dev->dev,
                                "Failed status: 0x%x, reset controller.\n",
                                csts);
@@ -1331,28 +1332,37 @@ static int nvme_create_io_queues(struct nvme_dev *dev)
        return ret >= 0 ? 0 : ret;
 }
 
+static ssize_t nvme_cmb_show(struct device *dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct nvme_dev *ndev = to_nvme_dev(dev_get_drvdata(dev));
+
+       return snprintf(buf, PAGE_SIZE, "cmbloc : x%08x\ncmbsz  : x%08x\n",
+                      ndev->cmbloc, ndev->cmbsz);
+}
+static DEVICE_ATTR(cmb, S_IRUGO, nvme_cmb_show, NULL);
+
 static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
 {
        u64 szu, size, offset;
-       u32 cmbloc;
        resource_size_t bar_size;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
        void __iomem *cmb;
        dma_addr_t dma_addr;
 
-       if (!use_cmb_sqes)
-               return NULL;
-
        dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ);
        if (!(NVME_CMB_SZ(dev->cmbsz)))
                return NULL;
+       dev->cmbloc = readl(dev->bar + NVME_REG_CMBLOC);
 
-       cmbloc = readl(dev->bar + NVME_REG_CMBLOC);
+       if (!use_cmb_sqes)
+               return NULL;
 
        szu = (u64)1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz));
        size = szu * NVME_CMB_SZ(dev->cmbsz);
-       offset = szu * NVME_CMB_OFST(cmbloc);
-       bar_size = pci_resource_len(pdev, NVME_CMB_BIR(cmbloc));
+       offset = szu * NVME_CMB_OFST(dev->cmbloc);
+       bar_size = pci_resource_len(pdev, NVME_CMB_BIR(dev->cmbloc));
 
        if (offset > bar_size)
                return NULL;
@@ -1365,7 +1375,7 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
        if (size > bar_size - offset)
                size = bar_size - offset;
 
-       dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(cmbloc)) + offset;
+       dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(dev->cmbloc)) + offset;
        cmb = ioremap_wc(dma_addr, size);
        if (!cmb)
                return NULL;
@@ -1511,9 +1521,9 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
        return 0;
 }
 
-static void nvme_disable_io_queues(struct nvme_dev *dev)
+static void nvme_disable_io_queues(struct nvme_dev *dev, int queues)
 {
-       int pass, queues = dev->online_queues - 1;
+       int pass;
        unsigned long timeout;
        u8 opcode = nvme_admin_delete_sq;
 
@@ -1616,9 +1626,25 @@ static int nvme_pci_enable(struct nvme_dev *dev)
                        dev->q_depth);
        }
 
-       if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2))
+       /*
+        * CMBs can currently only exist on >=1.2 PCIe devices. We only
+        * populate sysfs if a CMB is implemented. Note that we add the
+        * CMB attribute to the nvme_ctrl kobj which removes the need to remove
+        * it on exit. Since nvme_dev_attrs_group has no name we can pass
+        * NULL as final argument to sysfs_add_file_to_group.
+        */
+
+       if (readl(dev->bar + NVME_REG_VS) >= NVME_VS(1, 2, 0)) {
                dev->cmb = nvme_map_cmb(dev);
 
+               if (dev->cmbsz) {
+                       if (sysfs_add_file_to_group(&dev->ctrl.device->kobj,
+                                                   &dev_attr_cmb.attr, NULL))
+                               dev_warn(dev->dev,
+                                        "failed to add sysfs attribute for CMB\n");
+               }
+       }
+
        pci_enable_pcie_error_reporting(pdev);
        pci_save_state(pdev);
        return 0;
@@ -1649,7 +1675,7 @@ static void nvme_pci_disable(struct nvme_dev *dev)
 
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
 {
-       int i;
+       int i, queues;
        u32 csts = -1;
 
        del_timer_sync(&dev->watchdog_timer);
@@ -1660,6 +1686,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
                csts = readl(dev->bar + NVME_REG_CSTS);
        }
 
+       queues = dev->online_queues - 1;
        for (i = dev->queue_count - 1; i > 0; i--)
                nvme_suspend_queue(dev->queues[i]);
 
@@ -1671,7 +1698,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
                if (dev->queue_count)
                        nvme_suspend_queue(dev->queues[0]);
        } else {
-               nvme_disable_io_queues(dev);
+               nvme_disable_io_queues(dev, queues);
                nvme_disable_admin_queue(dev, shutdown);
        }
        nvme_pci_disable(dev);
@@ -1818,11 +1845,10 @@ static int nvme_reset(struct nvme_dev *dev)
 {
        if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
                return -ENODEV;
-
+       if (work_busy(&dev->reset_work))
+               return -ENODEV;
        if (!queue_work(nvme_workq, &dev->reset_work))
                return -EBUSY;
-
-       flush_work(&dev->reset_work);
        return 0;
 }
 
@@ -1846,7 +1872,12 @@ static int nvme_pci_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
 
 static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
 {
-       return nvme_reset(to_nvme_dev(ctrl));
+       struct nvme_dev *dev = to_nvme_dev(ctrl);
+       int ret = nvme_reset(dev);
+
+       if (!ret)
+               flush_work(&dev->reset_work);
+       return ret;
 }
 
 static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
@@ -1940,7 +1971,7 @@ static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
        if (prepare)
                nvme_dev_disable(dev, false);
        else
-               queue_work(nvme_workq, &dev->reset_work);
+               nvme_reset(dev);
 }
 
 static void nvme_shutdown(struct pci_dev *pdev)
@@ -2009,7 +2040,7 @@ static int nvme_resume(struct device *dev)
        struct pci_dev *pdev = to_pci_dev(dev);
        struct nvme_dev *ndev = pci_get_drvdata(pdev);
 
-       queue_work(nvme_workq, &ndev->reset_work);
+       nvme_reset(ndev);
        return 0;
 }
 #endif
@@ -2048,7 +2079,7 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
 
        dev_info(dev->ctrl.device, "restart after slot reset\n");
        pci_restore_state(pdev);
-       queue_work(nvme_workq, &dev->reset_work);
+       nvme_reset(dev);
        return PCI_ERS_RESULT_RECOVERED;
 }
 
index c2a0a1c..3eaa4d2 100644 (file)
@@ -606,7 +606,7 @@ static int nvme_fill_device_id_eui64(struct nvme_ns *ns, struct sg_io_hdr *hdr,
        eui = id_ns->eui64;
        len = sizeof(id_ns->eui64);
 
-       if (ns->ctrl->vs >= NVME_VS(1, 2)) {
+       if (ns->ctrl->vs >= NVME_VS(1, 2, 0)) {
                if (bitmap_empty(eui, len * 8)) {
                        eui = id_ns->nguid;
                        len = sizeof(id_ns->nguid);
@@ -679,7 +679,7 @@ static int nvme_trans_device_id_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
 {
        int res;
 
-       if (ns->ctrl->vs >= NVME_VS(1, 1)) {
+       if (ns->ctrl->vs >= NVME_VS(1, 1, 0)) {
                res = nvme_fill_device_id_eui64(ns, hdr, resp, alloc_len);
                if (res != -EOPNOTSUPP)
                        return res;
index 7ab9c93..6fe4c48 100644 (file)
@@ -199,7 +199,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
         */
 
        /* we support multiple ports and multiples hosts: */
-       id->mic = (1 << 0) | (1 << 1);
+       id->cmic = (1 << 0) | (1 << 1);
 
        /* no limit on data transfer sizes for now */
        id->mdts = 0;
@@ -511,13 +511,13 @@ int nvmet_parse_admin_cmd(struct nvmet_req *req)
        case nvme_admin_identify:
                req->data_len = 4096;
                switch (le32_to_cpu(cmd->identify.cns)) {
-               case 0x00:
+               case NVME_ID_CNS_NS:
                        req->execute = nvmet_execute_identify_ns;
                        return 0;
-               case 0x01:
+               case NVME_ID_CNS_CTRL:
                        req->execute = nvmet_execute_identify_ctrl;
                        return 0;
-               case 0x02:
+               case NVME_ID_CNS_NS_ACTIVE_LIST:
                        req->execute = nvmet_execute_identify_nslist;
                        return 0;
                }
index 6559d5a..b4cacb6 100644 (file)
@@ -882,7 +882,7 @@ struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
        if (!subsys)
                return NULL;
 
-       subsys->ver = (1 << 16) | (2 << 8) | 1; /* NVMe 1.2.1 */
+       subsys->ver = NVME_VS(1, 2, 1); /* NVMe 1.2.1 */
 
        switch (type) {
        case NVME_NQN_NVME:
index 6f65646..12f39ee 100644 (file)
@@ -54,7 +54,7 @@ static void nvmet_format_discovery_entry(struct nvmf_disc_rsp_page_hdr *hdr,
        /* we support only dynamic controllers */
        e->cntlid = cpu_to_le16(NVME_CNTLID_DYNAMIC);
        e->asqsz = cpu_to_le16(NVMF_AQ_DEPTH);
-       e->nqntype = type;
+       e->subtype = type;
        memcpy(e->trsvcid, port->disc_addr.trsvcid, NVMF_TRSVCID_SIZE);
        memcpy(e->traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
        memcpy(e->tsas.common, port->disc_addr.tsas.common, NVMF_TSAS_SIZE);
@@ -187,7 +187,7 @@ int nvmet_parse_discovery_cmd(struct nvmet_req *req)
        case nvme_admin_identify:
                req->data_len = 4096;
                switch (le32_to_cpu(cmd->identify.cns)) {
-               case 0x01:
+               case NVME_ID_CNS_CTRL:
                        req->execute =
                                nvmet_execute_identify_disc_ctrl;
                        return 0;
index 2cb7315..6537079 100644 (file)
@@ -247,6 +247,7 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
 
        pp = &pcie->pp;
        pp->dev = dev;
+       pcie->drvdata = match->data;
        pp->ops = pcie->drvdata->ops;
 
        dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
@@ -256,7 +257,6 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(pcie->pp.dbi_base);
        }
 
-       pcie->drvdata = match->data;
        pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
 
        if (!ls_pcie_is_bridge(pcie))
index 537f58a..8df6312 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
  *
- * Authors: Joao Pinto <jpinto@synopsys.com>
+ * Authors: Joao Pinto <jpmpinto@gmail.com>
  *
  * 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
index bfdd074..ad70507 100644 (file)
@@ -610,6 +610,7 @@ static int msi_verify_entries(struct pci_dev *dev)
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
  * @nvec: number of interrupts to allocate
+ * @affinity: flag to indicate cpu irq affinity mask should be set
  *
  * Setup the MSI capability structure of the device with the requested
  * number of interrupts.  A return value of zero indicates the successful
@@ -752,6 +753,7 @@ static void msix_program_entries(struct pci_dev *dev,
  * @dev: pointer to the pci_dev data structure of MSI-X device function
  * @entries: pointer to an array of struct msix_entry entries
  * @nvec: number of @entries
+ * @affinity: flag to indicate cpu irq affinity mask should be set
  *
  * Setup the MSI-X capability structure of device function with a
  * single MSI-X irq. A return of zero indicates the successful setup of
index c2ac764..a8ac4bc 100644 (file)
@@ -1011,7 +1011,7 @@ xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
        rc = acpi_dev_get_resources(adev, &resource_list,
                                    acpi_pmu_dev_add_resource, &res);
        acpi_dev_free_resource_list(&resource_list);
-       if (rc < 0 || IS_ERR(&res)) {
+       if (rc < 0) {
                dev_err(dev, "PMU type %d: No resource address found\n", type);
                goto err;
        }
index e1ab864..c8c72e8 100644 (file)
@@ -151,21 +151,21 @@ FUNC_GROUP_DECL(GPID0, F19, E21);
 
 #define GPID2_DESC      SIG_DESC_SET(SCU8C, 9)
 
-#define D20 26
+#define F20 26
 SIG_EXPR_LIST_DECL_SINGLE(SD2DAT0, SD2, SD2_DESC);
 SIG_EXPR_DECL(GPID2IN, GPID2, GPID2_DESC);
 SIG_EXPR_DECL(GPID2IN, GPID, GPID_DESC);
 SIG_EXPR_LIST_DECL_DUAL(GPID2IN, GPID2, GPID);
-MS_PIN_DECL(D20, GPIOD2, SD2DAT0, GPID2IN);
+MS_PIN_DECL(F20, GPIOD2, SD2DAT0, GPID2IN);
 
-#define D21 27
+#define D20 27
 SIG_EXPR_LIST_DECL_SINGLE(SD2DAT1, SD2, SD2_DESC);
 SIG_EXPR_DECL(GPID2OUT, GPID2, GPID2_DESC);
 SIG_EXPR_DECL(GPID2OUT, GPID, GPID_DESC);
 SIG_EXPR_LIST_DECL_DUAL(GPID2OUT, GPID2, GPID);
-MS_PIN_DECL(D21, GPIOD3, SD2DAT1, GPID2OUT);
+MS_PIN_DECL(D20, GPIOD3, SD2DAT1, GPID2OUT);
 
-FUNC_GROUP_DECL(GPID2, D20, D21);
+FUNC_GROUP_DECL(GPID2, F20, D20);
 
 #define GPIE_DESC      SIG_DESC_SET(HW_STRAP1, 21)
 #define GPIE0_DESC     SIG_DESC_SET(SCU8C, 12)
@@ -182,28 +182,88 @@ SIG_EXPR_LIST_DECL_SINGLE(NDCD3, NDCD3, SIG_DESC_SET(SCU80, 17));
 SIG_EXPR_DECL(GPIE0OUT, GPIE0, GPIE0_DESC);
 SIG_EXPR_DECL(GPIE0OUT, GPIE, GPIE_DESC);
 SIG_EXPR_LIST_DECL_DUAL(GPIE0OUT, GPIE0, GPIE);
-MS_PIN_DECL(C20, GPIE0, NDCD3, GPIE0OUT);
+MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
 
 FUNC_GROUP_DECL(GPIE0, B20, C20);
 
-#define SPI1_DESC      SIG_DESC_SET(HW_STRAP1, 13)
+#define SPI1_DESC              { HW_STRAP1, GENMASK(13, 12), 1, 0 }
+#define SPI1DEBUG_DESC         { HW_STRAP1, GENMASK(13, 12), 2, 0 }
+#define SPI1PASSTHRU_DESC      { HW_STRAP1, GENMASK(13, 12), 3, 0 }
+
 #define C18 64
-SIG_EXPR_LIST_DECL_SINGLE(SYSCS, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSCS, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSCS, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSCS, SPI1DEBUG, SPI1PASSTHRU);
 SS_PIN_DECL(C18, GPIOI0, SYSCS);
 
 #define E15 65
-SIG_EXPR_LIST_DECL_SINGLE(SYSCK, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSCK, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSCK, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSCK, SPI1DEBUG, SPI1PASSTHRU);
 SS_PIN_DECL(E15, GPIOI1, SYSCK);
 
-#define A14 66
-SIG_EXPR_LIST_DECL_SINGLE(SYSMOSI, SPI1, COND1, SPI1_DESC);
-SS_PIN_DECL(A14, GPIOI2, SYSMOSI);
+#define B16 66
+SIG_EXPR_DECL(SYSMOSI, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSMOSI, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSMOSI, SPI1DEBUG, SPI1PASSTHRU);
+SS_PIN_DECL(B16, GPIOI2, SYSMOSI);
 
 #define C16 67
-SIG_EXPR_LIST_DECL_SINGLE(SYSMISO, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SYSMISO, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SYSMISO, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL_DUAL(SYSMISO, SPI1DEBUG, SPI1PASSTHRU);
 SS_PIN_DECL(C16, GPIOI3, SYSMISO);
 
-FUNC_GROUP_DECL(SPI1, C18, E15, A14, C16);
+#define VB_DESC        SIG_DESC_SET(HW_STRAP1, 5)
+
+#define B15 68
+SIG_EXPR_DECL(SPI1CS0, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1CS0, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1CS0, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1CS0, SIG_EXPR_PTR(SPI1CS0, SPI1),
+                           SIG_EXPR_PTR(SPI1CS0, SPI1DEBUG),
+                           SIG_EXPR_PTR(SPI1CS0, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBCS, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(B15, GPIOI4, SPI1CS0, VBCS);
+
+#define C15 69
+SIG_EXPR_DECL(SPI1CK, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1CK, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1CK, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1CK, SIG_EXPR_PTR(SPI1CK, SPI1),
+                           SIG_EXPR_PTR(SPI1CK, SPI1DEBUG),
+                           SIG_EXPR_PTR(SPI1CK, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBCK, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(C15, GPIOI5, SPI1CK, VBCK);
+
+#define A14 70
+SIG_EXPR_DECL(SPI1MOSI, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1MOSI, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1MOSI, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1MOSI, SIG_EXPR_PTR(SPI1MOSI, SPI1),
+                           SIG_EXPR_PTR(SPI1MOSI, SPI1DEBUG),
+                           SIG_EXPR_PTR(SPI1MOSI, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBMOSI, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(A14, GPIOI6, SPI1MOSI, VBMOSI);
+
+#define A15 71
+SIG_EXPR_DECL(SPI1MISO, SPI1, COND1, SPI1_DESC);
+SIG_EXPR_DECL(SPI1MISO, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
+SIG_EXPR_DECL(SPI1MISO, SPI1PASSTHRU, COND1, SPI1PASSTHRU_DESC);
+SIG_EXPR_LIST_DECL(SPI1MISO, SIG_EXPR_PTR(SPI1MISO, SPI1),
+                           SIG_EXPR_PTR(SPI1MISO, SPI1DEBUG),
+                           SIG_EXPR_PTR(SPI1MISO, SPI1PASSTHRU));
+SIG_EXPR_LIST_DECL_SINGLE(VBMISO, VGABIOSROM, COND1, VB_DESC);
+MS_PIN_DECL(A15, GPIOI7, SPI1MISO, VBMISO);
+
+FUNC_GROUP_DECL(SPI1, B15, C15, A14, A15);
+FUNC_GROUP_DECL(SPI1DEBUG, C18, E15, B16, C16, B15, C15, A14, A15);
+FUNC_GROUP_DECL(SPI1PASSTHRU, C18, E15, B16, C16, B15, C15, A14, A15);
+FUNC_GROUP_DECL(VGABIOSROM, B15, C15, A14, A15);
+
+#define R2 72
+SIG_EXPR_LIST_DECL_SINGLE(SGPMCK, SGPM, SIG_DESC_SET(SCU84, 8));
+SS_PIN_DECL(R2, GPIOJ0, SGPMCK);
 
 #define L2 73
 SIG_EXPR_LIST_DECL_SINGLE(SGPMLD, SGPM, SIG_DESC_SET(SCU84, 9));
@@ -580,6 +640,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
        ASPEED_PINCTRL_PIN(A12),
        ASPEED_PINCTRL_PIN(A13),
        ASPEED_PINCTRL_PIN(A14),
+       ASPEED_PINCTRL_PIN(A15),
        ASPEED_PINCTRL_PIN(A2),
        ASPEED_PINCTRL_PIN(A3),
        ASPEED_PINCTRL_PIN(A4),
@@ -592,6 +653,8 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
        ASPEED_PINCTRL_PIN(B12),
        ASPEED_PINCTRL_PIN(B13),
        ASPEED_PINCTRL_PIN(B14),
+       ASPEED_PINCTRL_PIN(B15),
+       ASPEED_PINCTRL_PIN(B16),
        ASPEED_PINCTRL_PIN(B2),
        ASPEED_PINCTRL_PIN(B20),
        ASPEED_PINCTRL_PIN(B3),
@@ -603,6 +666,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
        ASPEED_PINCTRL_PIN(C12),
        ASPEED_PINCTRL_PIN(C13),
        ASPEED_PINCTRL_PIN(C14),
+       ASPEED_PINCTRL_PIN(C15),
        ASPEED_PINCTRL_PIN(C16),
        ASPEED_PINCTRL_PIN(C18),
        ASPEED_PINCTRL_PIN(C2),
@@ -614,7 +678,6 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
        ASPEED_PINCTRL_PIN(D10),
        ASPEED_PINCTRL_PIN(D2),
        ASPEED_PINCTRL_PIN(D20),
-       ASPEED_PINCTRL_PIN(D21),
        ASPEED_PINCTRL_PIN(D4),
        ASPEED_PINCTRL_PIN(D5),
        ASPEED_PINCTRL_PIN(D6),
@@ -630,6 +693,7 @@ static struct pinctrl_pin_desc aspeed_g5_pins[ASPEED_G5_NR_PINS] = {
        ASPEED_PINCTRL_PIN(E7),
        ASPEED_PINCTRL_PIN(E9),
        ASPEED_PINCTRL_PIN(F19),
+       ASPEED_PINCTRL_PIN(F20),
        ASPEED_PINCTRL_PIN(F9),
        ASPEED_PINCTRL_PIN(H20),
        ASPEED_PINCTRL_PIN(L1),
@@ -691,11 +755,14 @@ static const struct aspeed_pin_group aspeed_g5_groups[] = {
        ASPEED_PINCTRL_GROUP(RMII2),
        ASPEED_PINCTRL_GROUP(SD1),
        ASPEED_PINCTRL_GROUP(SPI1),
+       ASPEED_PINCTRL_GROUP(SPI1DEBUG),
+       ASPEED_PINCTRL_GROUP(SPI1PASSTHRU),
        ASPEED_PINCTRL_GROUP(TIMER4),
        ASPEED_PINCTRL_GROUP(TIMER5),
        ASPEED_PINCTRL_GROUP(TIMER6),
        ASPEED_PINCTRL_GROUP(TIMER7),
        ASPEED_PINCTRL_GROUP(TIMER8),
+       ASPEED_PINCTRL_GROUP(VGABIOSROM),
 };
 
 static const struct aspeed_pin_function aspeed_g5_functions[] = {
@@ -733,11 +800,14 @@ static const struct aspeed_pin_function aspeed_g5_functions[] = {
        ASPEED_PINCTRL_FUNC(RMII2),
        ASPEED_PINCTRL_FUNC(SD1),
        ASPEED_PINCTRL_FUNC(SPI1),
+       ASPEED_PINCTRL_FUNC(SPI1DEBUG),
+       ASPEED_PINCTRL_FUNC(SPI1PASSTHRU),
        ASPEED_PINCTRL_FUNC(TIMER4),
        ASPEED_PINCTRL_FUNC(TIMER5),
        ASPEED_PINCTRL_FUNC(TIMER6),
        ASPEED_PINCTRL_FUNC(TIMER7),
        ASPEED_PINCTRL_FUNC(TIMER8),
+       ASPEED_PINCTRL_FUNC(VGABIOSROM),
 };
 
 static struct aspeed_pinctrl_data aspeed_g5_pinctrl_data = {
index 0391f9f..49aeba9 100644 (file)
@@ -166,13 +166,9 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
                                bool enable, struct regmap *map)
 {
        int i;
-       bool ret;
-
-       ret = aspeed_sig_expr_eval(expr, enable, map);
-       if (ret)
-               return ret;
 
        for (i = 0; i < expr->ndescs; i++) {
+               bool ret;
                const struct aspeed_sig_desc *desc = &expr->descs[i];
                u32 pattern = enable ? desc->enable : desc->disable;
 
@@ -199,12 +195,18 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
 static bool aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
                                   struct regmap *map)
 {
+       if (aspeed_sig_expr_eval(expr, true, map))
+               return true;
+
        return aspeed_sig_expr_set(expr, true, map);
 }
 
 static bool aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
                                    struct regmap *map)
 {
+       if (!aspeed_sig_expr_eval(expr, true, map))
+               return true;
+
        return aspeed_sig_expr_set(expr, false, map);
 }
 
index d22a9fe..71bbeb9 100644 (file)
@@ -1808,6 +1808,8 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
                return PTR_ERR(vg->pctl_dev);
        }
 
+       raw_spin_lock_init(&vg->lock);
+
        ret = byt_gpio_probe(vg);
        if (ret) {
                pinctrl_unregister(vg->pctl_dev);
@@ -1815,7 +1817,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, vg);
-       raw_spin_lock_init(&vg->lock);
        pm_runtime_enable(&pdev->dev);
 
        return 0;
index 63387a4..0144376 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
 
+#include "../core.h"
 #include "pinctrl-intel.h"
 
 /* Offset from regs */
@@ -1056,6 +1057,26 @@ int intel_pinctrl_remove(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(intel_pinctrl_remove);
 
 #ifdef CONFIG_PM_SLEEP
+static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
+{
+       const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
+
+       if (!pd || !intel_pad_usable(pctrl, pin))
+               return false;
+
+       /*
+        * Only restore the pin if it is actually in use by the kernel (or
+        * by userspace). It is possible that some pins are used by the
+        * BIOS during resume and those are not always locked down so leave
+        * them alone.
+        */
+       if (pd->mux_owner || pd->gpio_owner ||
+           gpiochip_line_is_irq(&pctrl->chip, pin))
+               return true;
+
+       return false;
+}
+
 int intel_pinctrl_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -1069,7 +1090,7 @@ int intel_pinctrl_suspend(struct device *dev)
                const struct pinctrl_pin_desc *desc = &pctrl->soc->pins[i];
                u32 val;
 
-               if (!intel_pad_usable(pctrl, desc->number))
+               if (!intel_pinctrl_should_save(pctrl, desc->number))
                        continue;
 
                val = readl(intel_get_padcfg(pctrl, desc->number, PADCFG0));
@@ -1130,7 +1151,7 @@ int intel_pinctrl_resume(struct device *dev)
                void __iomem *padcfg;
                u32 val;
 
-               if (!intel_pad_usable(pctrl, desc->number))
+               if (!intel_pinctrl_should_save(pctrl, desc->number))
                        continue;
 
                padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);
index 07462d7..1aba2c7 100644 (file)
@@ -309,7 +309,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
                 * much memory to the process.
                 */
                down_read(&current->mm->mmap_sem);
-               ret = get_user_pages(address, 1, !is_write, 0, &page, NULL);
+               ret = get_user_pages(address, 1, is_write ? 0 : FOLL_WRITE,
+                               &page, NULL);
                up_read(&current->mm->mmap_sem);
                if (ret < 0)
                        break;
index 81b8dcc..b8a21d7 100644 (file)
@@ -576,6 +576,7 @@ config ASUS_WMI
 config ASUS_NB_WMI
        tristate "Asus Notebook WMI Driver"
        depends on ASUS_WMI
+       depends on SERIO_I8042 || SERIO_I8042 = n
        ---help---
          This is a driver for newer Asus notebooks. It adds extra features
          like wireless radio and bluetooth control, leds, hotkeys, backlight...
index d1a091b..a232394 100644 (file)
@@ -933,6 +933,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
                },
        },
+       {
+               .ident = "Lenovo YOGA 910-13IKB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 910-13IKB"),
+               },
+       },
        {}
 };
 
index 436dfe8..9013a58 100644 (file)
@@ -892,7 +892,8 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode,
                down_read(&current->mm->mmap_sem);
                pinned = get_user_pages(
                                (unsigned long)xfer->loc_addr & PAGE_MASK,
-                               nr_pages, dir == DMA_FROM_DEVICE, 0,
+                               nr_pages,
+                               dir == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
                                page_list, NULL);
                up_read(&current->mm->mmap_sem);
 
index 8b2558e..968c3ae 100644 (file)
@@ -154,7 +154,7 @@ const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro5_mio_reset_data[] = {
+const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
        UNIPHIER_MIO_RESET_SD(0, 0),
        UNIPHIER_MIO_RESET_SD(1, 1),
        UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
@@ -360,7 +360,7 @@ static const struct of_device_id uniphier_reset_match[] = {
                .compatible = "socionext,uniphier-ld20-reset",
                .data = uniphier_ld20_sys_reset_data,
        },
-       /* Media I/O reset */
+       /* Media I/O reset, SD reset */
        {
                .compatible = "socionext,uniphier-sld3-mio-reset",
                .data = uniphier_sld3_mio_reset_data,
@@ -378,20 +378,20 @@ static const struct of_device_id uniphier_reset_match[] = {
                .data = uniphier_sld3_mio_reset_data,
        },
        {
-               .compatible = "socionext,uniphier-pro5-mio-reset",
-               .data = uniphier_pro5_mio_reset_data,
+               .compatible = "socionext,uniphier-pro5-sd-reset",
+               .data = uniphier_pro5_sd_reset_data,
        },
        {
-               .compatible = "socionext,uniphier-pxs2-mio-reset",
-               .data = uniphier_pro5_mio_reset_data,
+               .compatible = "socionext,uniphier-pxs2-sd-reset",
+               .data = uniphier_pro5_sd_reset_data,
        },
        {
                .compatible = "socionext,uniphier-ld11-mio-reset",
                .data = uniphier_sld3_mio_reset_data,
        },
        {
-               .compatible = "socionext,uniphier-ld20-mio-reset",
-               .data = uniphier_pro5_mio_reset_data,
+               .compatible = "socionext,uniphier-ld20-sd-reset",
+               .data = uniphier_pro5_sd_reset_data,
        },
        /* Peripheral reset */
        {
index 831935a..a7a8847 100644 (file)
@@ -1205,7 +1205,7 @@ static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
                                 mdc, lpm);
                        return mdc;
                }
-               fcx_max_data = mdc * FCX_MAX_DATA_FACTOR;
+               fcx_max_data = (u32)mdc * FCX_MAX_DATA_FACTOR;
                if (fcx_max_data < private->fcx_max_data) {
                        dev_warn(&device->cdev->dev,
                                 "The maximum data size for zHPF requests %u "
@@ -1675,7 +1675,7 @@ static u32 get_fcx_max_data(struct dasd_device *device)
                         " data size for zHPF requests failed\n");
                return 0;
        } else
-               return mdc * FCX_MAX_DATA_FACTOR;
+               return (u32)mdc * FCX_MAX_DATA_FACTOR;
 }
 
 /*
index 46be25c..876c7e6 100644 (file)
@@ -780,7 +780,7 @@ static int cfg_wait_idle(void)
 static int __init chp_init(void)
 {
        struct chp_id chpid;
-       int ret;
+       int state, ret;
 
        ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw);
        if (ret)
@@ -791,7 +791,9 @@ static int __init chp_init(void)
                return 0;
        /* Register available channel-paths. */
        chp_id_for_each(&chpid) {
-               if (chp_info_get_status(chpid) != CHP_STATUS_NOT_RECOGNIZED)
+               state = chp_info_get_status(chpid);
+               if (state == CHP_STATUS_CONFIGURED ||
+                   state == CHP_STATUS_STANDBY)
                        chp_new(chpid);
        }
 
index 637cf89..5810019 100644 (file)
@@ -384,7 +384,7 @@ void zfcp_dbf_san(char *tag, struct zfcp_dbf *dbf,
        /* if (len > rec_len):
         * dump data up to cap_len ignoring small duplicate in rec->payload
         */
-       spin_lock_irqsave(&dbf->pay_lock, flags);
+       spin_lock(&dbf->pay_lock);
        memset(payload, 0, sizeof(*payload));
        memcpy(payload->area, paytag, ZFCP_DBF_TAG_LEN);
        payload->fsf_req_id = req_id;
index db27390..790babc 100644 (file)
@@ -353,7 +353,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 #endif
 
 
-static int probe_irq __initdata;
+static int probe_irq;
 
 /**
  * probe_intr  -       helper for IRQ autoprobe
@@ -365,7 +365,7 @@ static int probe_irq __initdata;
  * used by the IRQ probe code.
  */
 
-static irqreturn_t __init probe_intr(int irq, void *dev_id)
+static irqreturn_t probe_intr(int irq, void *dev_id)
 {
        probe_irq = irq;
        return IRQ_HANDLED;
@@ -380,7 +380,7 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id)
  * and then looking to see what interrupt actually turned up.
  */
 
-static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
+static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
                                                int possible)
 {
        struct NCR5380_hostdata *hostdata = shost_priv(instance);
index 68138a6..d9239c2 100644 (file)
@@ -900,8 +900,9 @@ void hwi_ring_cq_db(struct beiscsi_hba *phba,
 static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
 {
        struct sgl_handle *psgl_handle;
+       unsigned long flags;
 
-       spin_lock_bh(&phba->io_sgl_lock);
+       spin_lock_irqsave(&phba->io_sgl_lock, flags);
        if (phba->io_sgl_hndl_avbl) {
                beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
                            "BM_%d : In alloc_io_sgl_handle,"
@@ -919,14 +920,16 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
                        phba->io_sgl_alloc_index++;
        } else
                psgl_handle = NULL;
-       spin_unlock_bh(&phba->io_sgl_lock);
+       spin_unlock_irqrestore(&phba->io_sgl_lock, flags);
        return psgl_handle;
 }
 
 static void
 free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 {
-       spin_lock_bh(&phba->io_sgl_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&phba->io_sgl_lock, flags);
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
                    "BM_%d : In free_,io_sgl_free_index=%d\n",
                    phba->io_sgl_free_index);
@@ -941,7 +944,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
                             "value there=%p\n", phba->io_sgl_free_index,
                             phba->io_sgl_hndl_base
                             [phba->io_sgl_free_index]);
-                spin_unlock_bh(&phba->io_sgl_lock);
+                spin_unlock_irqrestore(&phba->io_sgl_lock, flags);
                return;
        }
        phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
@@ -950,7 +953,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
                phba->io_sgl_free_index = 0;
        else
                phba->io_sgl_free_index++;
-       spin_unlock_bh(&phba->io_sgl_lock);
+       spin_unlock_irqrestore(&phba->io_sgl_lock, flags);
 }
 
 static inline struct wrb_handle *
@@ -958,15 +961,16 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context,
                       unsigned int wrbs_per_cxn)
 {
        struct wrb_handle *pwrb_handle;
+       unsigned long flags;
 
-       spin_lock_bh(&pwrb_context->wrb_lock);
+       spin_lock_irqsave(&pwrb_context->wrb_lock, flags);
        pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index];
        pwrb_context->wrb_handles_available--;
        if (pwrb_context->alloc_index == (wrbs_per_cxn - 1))
                pwrb_context->alloc_index = 0;
        else
                pwrb_context->alloc_index++;
-       spin_unlock_bh(&pwrb_context->wrb_lock);
+       spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags);
 
        if (pwrb_handle)
                memset(pwrb_handle->pwrb, 0, sizeof(*pwrb_handle->pwrb));
@@ -1001,14 +1005,16 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context,
                       struct wrb_handle *pwrb_handle,
                       unsigned int wrbs_per_cxn)
 {
-       spin_lock_bh(&pwrb_context->wrb_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pwrb_context->wrb_lock, flags);
        pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
        pwrb_context->wrb_handles_available++;
        if (pwrb_context->free_index == (wrbs_per_cxn - 1))
                pwrb_context->free_index = 0;
        else
                pwrb_context->free_index++;
-       spin_unlock_bh(&pwrb_context->wrb_lock);
+       spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags);
 }
 
 /**
@@ -1037,8 +1043,9 @@ free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
 static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
 {
        struct sgl_handle *psgl_handle;
+       unsigned long flags;
 
-       spin_lock_bh(&phba->mgmt_sgl_lock);
+       spin_lock_irqsave(&phba->mgmt_sgl_lock, flags);
        if (phba->eh_sgl_hndl_avbl) {
                psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
                phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
@@ -1056,14 +1063,16 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
                        phba->eh_sgl_alloc_index++;
        } else
                psgl_handle = NULL;
-       spin_unlock_bh(&phba->mgmt_sgl_lock);
+       spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags);
        return psgl_handle;
 }
 
 void
 free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
 {
-       spin_lock_bh(&phba->mgmt_sgl_lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&phba->mgmt_sgl_lock, flags);
        beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
                    "BM_%d : In  free_mgmt_sgl_handle,"
                    "eh_sgl_free_index=%d\n",
@@ -1078,7 +1087,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
                            "BM_%d : Double Free in eh SGL ,"
                            "eh_sgl_free_index=%d\n",
                            phba->eh_sgl_free_index);
-               spin_unlock_bh(&phba->mgmt_sgl_lock);
+               spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags);
                return;
        }
        phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle;
@@ -1088,7 +1097,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
                phba->eh_sgl_free_index = 0;
        else
                phba->eh_sgl_free_index++;
-       spin_unlock_bh(&phba->mgmt_sgl_lock);
+       spin_unlock_irqrestore(&phba->mgmt_sgl_lock, flags);
 }
 
 static void
index a8762a3..5324741 100644 (file)
@@ -2586,7 +2586,6 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
        struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
        u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
        u32 fd_ioasc;
-       char *envp[] = { "ASYNC_ERR_LOG=1", NULL };
 
        if (ioa_cfg->sis64)
                fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc);
@@ -2607,8 +2606,8 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
        }
 
        list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_report_q);
+       schedule_work(&ioa_cfg->work_q);
        hostrcb = ipr_get_free_hostrcb(ioa_cfg);
-       kobject_uevent_env(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE, envp);
 
        ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb);
 }
index c051694..f9b6fba 100644 (file)
@@ -791,9 +791,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 
 free_task:
        /* regular RX path uses back_lock */
-       spin_lock_bh(&session->back_lock);
+       spin_lock(&session->back_lock);
        __iscsi_put_task(task);
-       spin_unlock_bh(&session->back_lock);
+       spin_unlock(&session->back_lock);
        return NULL;
 }
 
index 54d446c..b8d3b97 100644 (file)
@@ -36,9 +36,9 @@ struct scsi_dh_blist {
 };
 
 static const struct scsi_dh_blist scsi_dh_blist[] = {
-       {"DGC", "RAID",                 "clariion" },
-       {"DGC", "DISK",                 "clariion" },
-       {"DGC", "VRAID",                "clariion" },
+       {"DGC", "RAID",                 "emc" },
+       {"DGC", "DISK",                 "emc" },
+       {"DGC", "VRAID",                "emc" },
 
        {"COMPAQ", "MSA1000 VOLUME",    "hp_sw" },
        {"COMPAQ", "HSV110",            "hp_sw" },
index 212e98d..6f7128f 100644 (file)
@@ -1307,7 +1307,6 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget,
 static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                                enum scsi_scan_mode rescan)
 {
-       char devname[64];
        unsigned char scsi_cmd[MAX_COMMAND_SIZE];
        unsigned int length;
        u64 lun;
@@ -1349,9 +1348,6 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                }
        }
 
-       sprintf(devname, "host %d channel %d id %d",
-               shost->host_no, sdev->channel, sdev->id);
-
        /*
         * Allocate enough to hold the header (the same size as one scsi_lun)
         * plus the number of luns we are requesting.  511 was the default
@@ -1470,12 +1466,12 @@ retry:
  out_err:
        kfree(lun_data);
  out:
-       scsi_device_put(sdev);
        if (scsi_device_created(sdev))
                /*
                 * the sdev we used didn't appear in the report luns scan
                 */
                __scsi_remove_device(sdev);
+       scsi_device_put(sdev);
        return ret;
 }
 
index 7af5226..618422e 100644 (file)
@@ -4922,9 +4922,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
        res = get_user_pages_unlocked(
                uaddr,
                nr_pages,
-               rw == READ,
-               0, /* don't force */
-               pages);
+               pages,
+               rw == READ ? FOLL_WRITE : 0); /* don't force */
 
        /* Errors and no page mapped should return here */
        if (res < nr_pages)
index 396ded5..209a8f7 100644 (file)
@@ -1187,8 +1187,10 @@ int ion_query_heaps(struct ion_client *client, struct ion_heap_query *query)
                hdata.type = heap->type;
                hdata.heap_id = heap->id;
 
-               ret = copy_to_user(&buffer[cnt],
-                                  &hdata, sizeof(hdata));
+               if (copy_to_user(&buffer[cnt], &hdata, sizeof(hdata))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
 
                cnt++;
                if (cnt >= max_cnt)
index 15bac92..46b2bb9 100644 (file)
@@ -107,7 +107,7 @@ struct ion_platform_data *ion_parse_dt(struct platform_device *pdev,
 
                heap_pdev = of_platform_device_create(node, heaps[i].name,
                                                      &pdev->dev);
-               if (!pdev)
+               if (!heap_pdev)
                        return ERR_PTR(-ENOMEM);
                heap_pdev->dev.platform_data = &heaps[i];
 
index e36ee98..34307ac 100644 (file)
@@ -128,6 +128,7 @@ int arche_platform_change_state(enum arche_platform_state state,
        pdev = of_find_device_by_node(np);
        if (!pdev) {
                pr_err("arche-platform device not found\n");
+               of_node_put(np);
                return -ENODEV;
        }
 
index 071bb1c..baab460 100644 (file)
@@ -1548,7 +1548,8 @@ static int ap_probe(struct usb_interface *interface,
        INIT_LIST_HEAD(&es2->arpcs);
        spin_lock_init(&es2->arpc_lock);
 
-       if (es2_arpc_in_enable(es2))
+       retval = es2_arpc_in_enable(es2);
+       if (retval)
                goto error;
 
        retval = gb_hd_add(hd);
index 5e06e42..250caa0 100644 (file)
@@ -702,15 +702,13 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
        ret = gb_gpio_irqchip_add(gpio, irqc, 0,
                                   handle_level_irq, IRQ_TYPE_NONE);
        if (ret) {
-               dev_err(&connection->bundle->dev,
-                       "failed to add irq chip: %d\n", ret);
+               dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret);
                goto exit_line_free;
        }
 
        ret = gpiochip_add(gpio);
        if (ret) {
-               dev_err(&connection->bundle->dev,
-                       "failed to add gpio chip: %d\n", ret);
+               dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
                goto exit_gpio_irqchip_remove;
        }
 
index 69f67dd..660b467 100644 (file)
@@ -127,7 +127,7 @@ struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id,
        return module;
 
 err_put_interfaces:
-       for (--i; i > 0; --i)
+       for (--i; i >= 0; --i)
                gb_interface_put(module->interfaces[i]);
 
        put_device(&module->dev);
index 5ee7954..2633d2b 100644 (file)
@@ -888,7 +888,7 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev,
        minor = alloc_minor(gb_tty);
        if (minor < 0) {
                if (minor == -ENOSPC) {
-                       dev_err(&connection->bundle->dev,
+                       dev_err(&gbphy_dev->dev,
                                "no more free minor numbers\n");
                        retval = -ENODEV;
                } else {
index d626125..564b36d 100644 (file)
@@ -468,6 +468,8 @@ static inline int __sca3000_get_base_freq(struct sca3000_state *st,
        case SCA3000_MEAS_MODE_OP_2:
                *base_freq = info->option_mode_2_freq;
                break;
+       default:
+               ret = -EINVAL;
        }
 error_ret:
        return ret;
index 6eae605..23fda9d 100644 (file)
@@ -871,12 +871,10 @@ static ssize_t xattr_cache_store(struct kobject *kobj,
 }
 LUSTRE_RW_ATTR(xattr_cache);
 
-static ssize_t unstable_stats_show(struct kobject *kobj,
-                                  struct attribute *attr,
-                                  char *buf)
+static int ll_unstable_stats_seq_show(struct seq_file *m, void *v)
 {
-       struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
-                                             ll_kobj);
+       struct super_block     *sb    = m->private;
+       struct ll_sb_info      *sbi   = ll_s2sbi(sb);
        struct cl_client_cache *cache = sbi->ll_cache;
        long pages;
        int mb;
@@ -884,19 +882,21 @@ static ssize_t unstable_stats_show(struct kobject *kobj,
        pages = atomic_long_read(&cache->ccc_unstable_nr);
        mb = (pages * PAGE_SIZE) >> 20;
 
-       return sprintf(buf, "unstable_check:     %8d\n"
-                           "unstable_pages: %12ld\n"
-                           "unstable_mb:        %8d\n",
-                           cache->ccc_unstable_check, pages, mb);
+       seq_printf(m,
+                  "unstable_check:     %8d\n"
+                  "unstable_pages: %12ld\n"
+                  "unstable_mb:        %8d\n",
+                  cache->ccc_unstable_check, pages, mb);
+
+       return 0;
 }
 
-static ssize_t unstable_stats_store(struct kobject *kobj,
-                                   struct attribute *attr,
-                                   const char *buffer,
-                                   size_t count)
+static ssize_t ll_unstable_stats_seq_write(struct file *file,
+                                          const char __user *buffer,
+                                          size_t count, loff_t *off)
 {
-       struct ll_sb_info *sbi = container_of(kobj, struct ll_sb_info,
-                                             ll_kobj);
+       struct super_block *sb = ((struct seq_file *)file->private_data)->private;
+       struct ll_sb_info *sbi = ll_s2sbi(sb);
        char kernbuf[128];
        int val, rc;
 
@@ -922,7 +922,7 @@ static ssize_t unstable_stats_store(struct kobject *kobj,
 
        return count;
 }
-LUSTRE_RW_ATTR(unstable_stats);
+LPROC_SEQ_FOPS(ll_unstable_stats);
 
 static ssize_t root_squash_show(struct kobject *kobj, struct attribute *attr,
                                char *buf)
@@ -995,6 +995,7 @@ static struct lprocfs_vars lprocfs_llite_obd_vars[] = {
        /* { "filegroups",   lprocfs_rd_filegroups,  0, 0 }, */
        { "max_cached_mb",    &ll_max_cached_mb_fops, NULL },
        { "statahead_stats",  &ll_statahead_stats_fops, NULL, 0 },
+       { "unstable_stats",   &ll_unstable_stats_fops, NULL },
        { "sbi_flags",        &ll_sbi_flags_fops, NULL, 0 },
        { .name =               "nosquash_nids",
          .fops =               &ll_nosquash_nids_fops          },
@@ -1026,7 +1027,6 @@ static struct attribute *llite_attrs[] = {
        &lustre_attr_max_easize.attr,
        &lustre_attr_default_easize.attr,
        &lustre_attr_xattr_cache.attr,
-       &lustre_attr_unstable_stats.attr,
        &lustre_attr_root_squash.attr,
        NULL,
 };
index c29040f..1091b9f 100644 (file)
@@ -423,8 +423,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
                actual_pages = get_user_pages(task, task->mm,
                                          (unsigned long)buf & ~(PAGE_SIZE - 1),
                                          num_pages,
-                                         (type == PAGELIST_READ) /*Write */ ,
-                                         0 /*Force */ ,
+                                         (type == PAGELIST_READ) ? FOLL_WRITE : 0,
                                          pages,
                                          NULL /*vmas */);
                up_read(&task->mm->mmap_sem);
index e11c0e0..7b6cd4d 100644 (file)
@@ -1477,8 +1477,7 @@ dump_phys_mem(void *virt_addr, uint32_t num_bytes)
                current->mm,              /* mm */
                (unsigned long)virt_addr, /* start */
                num_pages,                /* len */
-               0,                        /* write */
-               0,                        /* force */
+               0,                        /* gup_flags */
                pages,                    /* pages (array of page pointers) */
                NULL);                    /* vmas */
        up_read(&current->mm->mmap_sem);
index 78f5613..6ab7443 100644 (file)
@@ -3388,7 +3388,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
 
        clients_count++;
 
-       destroy_workqueue(hif_workqueue);
 _fail_:
        return result;
 }
index 39b928c..b7d747e 100644 (file)
@@ -1804,6 +1804,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * Otherwise, initiator is not expecting a NOPIN is response.
         * Just ignore for now.
         */
+
+       if (cmd)
+               iscsit_free_cmd(cmd, false);
+
         return 0;
 }
 EXPORT_SYMBOL(iscsit_process_nop_out);
@@ -2982,7 +2986,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
 
        pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
                " StatSN: 0x%08x, Length %u\n", (nopout_response) ?
-               "Solicitied" : "Unsolicitied", cmd->init_task_tag,
+               "Solicited" : "Unsolicited", cmd->init_task_tag,
                cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
 }
 EXPORT_SYMBOL(iscsit_build_nopin_rsp);
index adf419f..15f79a2 100644 (file)
@@ -434,7 +434,7 @@ static int iscsi_login_zero_tsih_s2(
 
                /*
                 * Make MaxRecvDataSegmentLength PAGE_SIZE aligned for
-                * Immediate Data + Unsolicitied Data-OUT if necessary..
+                * Immediate Data + Unsolicited Data-OUT if necessary..
                 */
                param = iscsi_find_param_from_key("MaxRecvDataSegmentLength",
                                                  conn->param_list);
@@ -646,7 +646,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
 {
        struct iscsi_session *sess = conn->sess;
        /*
-        * FIXME: Unsolicitied NopIN support for ISER
+        * FIXME: Unsolicited NopIN support for ISER
         */
        if (conn->conn_transport->transport_type == ISCSI_INFINIBAND)
                return;
index 6094a6b..7dfefd6 100644 (file)
@@ -754,15 +754,7 @@ EXPORT_SYMBOL(target_complete_cmd);
 
 void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
 {
-       if (scsi_status != SAM_STAT_GOOD) {
-               return;
-       }
-
-       /*
-        * Calculate new residual count based upon length of SCSI data
-        * transferred.
-        */
-       if (length < cmd->data_length) {
+       if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
                if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
                        cmd->residual_count += cmd->data_length - length;
                } else {
@@ -771,12 +763,6 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len
                }
 
                cmd->data_length = length;
-       } else if (length > cmd->data_length) {
-               cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
-               cmd->residual_count = length - cmd->data_length;
-       } else {
-               cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT);
-               cmd->residual_count = 0;
        }
 
        target_complete_cmd(cmd, scsi_status);
@@ -1706,6 +1692,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
        case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
        case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
+       case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
                break;
        case TCM_OUT_OF_RESOURCES:
                sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2547,8 +2534,12 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
         * fabric acknowledgement that requires two target_put_sess_cmd()
         * invocations before se_cmd descriptor release.
         */
-       if (ack_kref)
-               kref_get(&se_cmd->cmd_kref);
+       if (ack_kref) {
+               if (!kref_get_unless_zero(&se_cmd->cmd_kref))
+                       return -EINVAL;
+
+               se_cmd->se_cmd_flags |= SCF_ACK_KREF;
+       }
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (se_sess->sess_tearing_down) {
@@ -2627,7 +2618,7 @@ EXPORT_SYMBOL(target_put_sess_cmd);
  */
 void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
 {
-       struct se_cmd *se_cmd;
+       struct se_cmd *se_cmd, *tmp_cmd;
        unsigned long flags;
        int rc;
 
@@ -2639,14 +2630,16 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
        se_sess->sess_tearing_down = 1;
        list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
 
-       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list) {
+       list_for_each_entry_safe(se_cmd, tmp_cmd,
+                                &se_sess->sess_wait_list, se_cmd_list) {
                rc = kref_get_unless_zero(&se_cmd->cmd_kref);
                if (rc) {
                        se_cmd->cmd_wait_set = 1;
                        spin_lock(&se_cmd->t_state_lock);
                        se_cmd->transport_state |= CMD_T_FABRIC_STOP;
                        spin_unlock(&se_cmd->t_state_lock);
-               }
+               } else
+                       list_del_init(&se_cmd->se_cmd_list);
        }
 
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
@@ -2871,6 +2864,12 @@ static const struct sense_info sense_info_table[] = {
                .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
                .add_sector_info = true,
        },
+       [TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = {
+               .key = COPY_ABORTED,
+               .asc = 0x0d,
+               .ascq = 0x02, /* COPY TARGET DEVICE NOT REACHABLE */
+
+       },
        [TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
                /*
                 * Returning ILLEGAL REQUEST would cause immediate IO errors on
index 62bf4fe..4756250 100644 (file)
@@ -96,7 +96,7 @@ struct tcmu_dev {
        size_t dev_size;
        u32 cmdr_size;
        u32 cmdr_last_cleaned;
-       /* Offset of data ring from start of mb */
+       /* Offset of data area from start of mb */
        /* Must add data_off and mb_addr to get the address */
        size_t data_off;
        size_t data_size;
@@ -349,7 +349,7 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap)
 
 /*
  * We can't queue a command until we have space available on the cmd ring *and*
- * space available on the data ring.
+ * space available on the data area.
  *
  * Called with ring lock held.
  */
@@ -389,7 +389,8 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d
        return true;
 }
 
-static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
+static sense_reason_t
+tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 {
        struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
        struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
@@ -405,7 +406,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS);
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
-               return -EINVAL;
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
        /*
         * Must be a certain minimum size for response sense info, but
@@ -432,11 +433,14 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
                data_length += se_cmd->t_bidi_data_sg->length;
        }
-       if ((command_size > (udev->cmdr_size / 2))
-           || data_length > udev->data_size)
-               pr_warn("TCMU: Request of size %zu/%zu may be too big for %u/%zu "
-                       "cmd/data ring buffers\n", command_size, data_length,
+       if ((command_size > (udev->cmdr_size / 2)) ||
+           data_length > udev->data_size) {
+               pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu "
+                       "cmd ring/data area\n", command_size, data_length,
                        udev->cmdr_size, udev->data_size);
+               spin_unlock_irq(&udev->cmdr_lock);
+               return TCM_INVALID_CDB_FIELD;
+       }
 
        while (!is_ring_space_avail(udev, command_size, data_length)) {
                int ret;
@@ -450,7 +454,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                finish_wait(&udev->wait_cmdr, &__wait);
                if (!ret) {
                        pr_warn("tcmu: command timed out\n");
-                       return -ETIMEDOUT;
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                }
 
                spin_lock_irq(&udev->cmdr_lock);
@@ -487,9 +491,7 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
        bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS);
 
-       /*
-        * Fix up iovecs, and handle if allocation in data ring wrapped.
-        */
+       /* Handle allocating space from the data area */
        iov = &entry->req.iov[0];
        iov_cnt = 0;
        copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE
@@ -526,10 +528,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        mod_timer(&udev->timeout,
                round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT)));
 
-       return 0;
+       return TCM_NO_SENSE;
 }
 
-static int tcmu_queue_cmd(struct se_cmd *se_cmd)
+static sense_reason_t
+tcmu_queue_cmd(struct se_cmd *se_cmd)
 {
        struct se_device *se_dev = se_cmd->se_dev;
        struct tcmu_dev *udev = TCMU_DEV(se_dev);
@@ -538,10 +541,10 @@ static int tcmu_queue_cmd(struct se_cmd *se_cmd)
 
        tcmu_cmd = tcmu_alloc_cmd(se_cmd);
        if (!tcmu_cmd)
-               return -ENOMEM;
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
        ret = tcmu_queue_cmd_ring(tcmu_cmd);
-       if (ret < 0) {
+       if (ret != TCM_NO_SENSE) {
                pr_err("TCMU: Could not queue command\n");
                spin_lock_irq(&udev->commands_lock);
                idr_remove(&udev->commands, tcmu_cmd->cmd_id);
@@ -561,7 +564,7 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
                /*
                 * cmd has been completed already from timeout, just reclaim
-                * data ring space and free cmd
+                * data area space and free cmd
                 */
                free_data_area(udev, cmd);
 
@@ -1128,21 +1131,10 @@ static sector_t tcmu_get_blocks(struct se_device *dev)
                       dev->dev_attrib.block_size);
 }
 
-static sense_reason_t
-tcmu_pass_op(struct se_cmd *se_cmd)
-{
-       int ret = tcmu_queue_cmd(se_cmd);
-
-       if (ret != 0)
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-       else
-               return TCM_NO_SENSE;
-}
-
 static sense_reason_t
 tcmu_parse_cdb(struct se_cmd *cmd)
 {
-       return passthrough_parse_cdb(cmd, tcmu_pass_op);
+       return passthrough_parse_cdb(cmd, tcmu_queue_cmd);
 }
 
 static const struct target_backend_ops tcmu_ops = {
index 75cd854..094a144 100644 (file)
@@ -104,7 +104,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
        }
        mutex_unlock(&g_device_mutex);
 
-       pr_err("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
+       pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
        return -EINVAL;
 }
 
@@ -185,7 +185,7 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
 
 static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
                                struct xcopy_op *xop, unsigned char *p,
-                               unsigned short tdll)
+                               unsigned short tdll, sense_reason_t *sense_ret)
 {
        struct se_device *local_dev = se_cmd->se_dev;
        unsigned char *desc = p;
@@ -193,6 +193,8 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
        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);
@@ -243,9 +245,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
                rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
        else
                rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
-
-       if (rc < 0)
+       /*
+        * If a matching IEEE NAA 0x83 descriptor for the requested device
+        * is not located on this node, return COPY_ABORTED with ASQ/ASQC
+        * 0x0d/0x02 - COPY_TARGET_DEVICE_NOT_REACHABLE to request the
+        * initiator to fall back to normal copy method.
+        */
+       if (rc < 0) {
+               *sense_ret = TCM_COPY_TARGET_DEVICE_NOT_REACHABLE;
                goto out;
+       }
 
        pr_debug("XCOPY TGT desc: Source dev: %p NAA IEEE WWN: 0x%16phN\n",
                 xop->src_dev, &xop->src_tid_wwn[0]);
@@ -653,6 +662,7 @@ static int target_xcopy_read_source(
        rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
                                remote_port, true);
        if (rc < 0) {
+               ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
                transport_generic_free_cmd(se_cmd, 0);
                return rc;
        }
@@ -664,6 +674,7 @@ static int target_xcopy_read_source(
 
        rc = target_xcopy_issue_pt_cmd(xpt_cmd);
        if (rc < 0) {
+               ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
                transport_generic_free_cmd(se_cmd, 0);
                return rc;
        }
@@ -714,6 +725,7 @@ static int target_xcopy_write_destination(
                                remote_port, false);
        if (rc < 0) {
                struct se_cmd *src_cmd = &xop->src_pt_cmd->se_cmd;
+               ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
                /*
                 * If the failure happened before the t_mem_list hand-off in
                 * target_xcopy_setup_pt_cmd(), Reset memory + clear flag so that
@@ -729,6 +741,7 @@ static int target_xcopy_write_destination(
 
        rc = target_xcopy_issue_pt_cmd(xpt_cmd);
        if (rc < 0) {
+               ec_cmd->scsi_status = xpt_cmd->se_cmd.scsi_status;
                se_cmd->se_cmd_flags &= ~SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
                transport_generic_free_cmd(se_cmd, 0);
                return rc;
@@ -815,9 +828,14 @@ static void target_xcopy_do_work(struct work_struct *work)
 out:
        xcopy_pt_undepend_remotedev(xop);
        kfree(xop);
-
-       pr_warn("target_xcopy_do_work: Setting X-COPY CHECK_CONDITION -> sending response\n");
-       ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
+       /*
+        * Don't override an error scsi status if it has already been set
+        */
+       if (ec_cmd->scsi_status == SAM_STAT_GOOD) {
+               pr_warn_ratelimited("target_xcopy_do_work: rc: %d, Setting X-COPY"
+                       " CHECK_CONDITION -> sending response\n", rc);
+               ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
+       }
        target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION);
 }
 
@@ -875,7 +893,7 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
                " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
                tdll, sdll, inline_dl);
 
-       rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll);
+       rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
        if (rc <= 0)
                goto out;
 
index 216e18c..ff5de9a 100644 (file)
@@ -572,10 +572,10 @@ static void ft_send_work(struct work_struct *work)
        if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
                              &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
                              ntohl(fcp->fc_dl), task_attr, data_dir,
-                             TARGET_SCF_ACK_KREF))
+                             TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID))
                goto err;
 
-       pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
+       pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd);
        return;
 
 err:
index 6ffbb60..fd5c3de 100644 (file)
 
 #include "tcm_fc.h"
 
+#define TFC_SESS_DBG(lport, fmt, args...) \
+       pr_debug("host%u: rport %6.6x: " fmt,      \
+                (lport)->host->host_no,           \
+                (lport)->port_id, ##args )
+
 static void ft_sess_delete_all(struct ft_tport *);
 
 /*
@@ -167,24 +172,29 @@ static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id)
        struct ft_tport *tport;
        struct hlist_head *head;
        struct ft_sess *sess;
+       char *reason = "no session created";
 
        rcu_read_lock();
        tport = rcu_dereference(lport->prov[FC_TYPE_FCP]);
-       if (!tport)
+       if (!tport) {
+               reason = "not an FCP port";
                goto out;
+       }
 
        head = &tport->hash[ft_sess_hash(port_id)];
        hlist_for_each_entry_rcu(sess, head, hash) {
                if (sess->port_id == port_id) {
                        kref_get(&sess->kref);
                        rcu_read_unlock();
-                       pr_debug("port_id %x found %p\n", port_id, sess);
+                       TFC_SESS_DBG(lport, "port_id %x found %p\n",
+                                    port_id, sess);
                        return sess;
                }
        }
 out:
        rcu_read_unlock();
-       pr_debug("port_id %x not found\n", port_id);
+       TFC_SESS_DBG(lport, "port_id %x not found, %s\n",
+                    port_id, reason);
        return NULL;
 }
 
@@ -195,7 +205,7 @@ static int ft_sess_alloc_cb(struct se_portal_group *se_tpg,
        struct ft_tport *tport = sess->tport;
        struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)];
 
-       pr_debug("port_id %x sess %p\n", sess->port_id, sess);
+       TFC_SESS_DBG(tport->lport, "port_id %x sess %p\n", sess->port_id, sess);
        hlist_add_head_rcu(&sess->hash, head);
        tport->sess_count++;
 
@@ -223,7 +233,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
 
        sess = kzalloc(sizeof(*sess), GFP_KERNEL);
        if (!sess)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        kref_init(&sess->kref); /* ref for table entry */
        sess->tport = tport;
@@ -234,8 +244,9 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
                                             TARGET_PROT_NORMAL, &initiatorname[0],
                                             sess, ft_sess_alloc_cb);
        if (IS_ERR(sess->se_sess)) {
+               int rc = PTR_ERR(sess->se_sess);
                kfree(sess);
-               return NULL;
+               sess = ERR_PTR(rc);
        }
        return sess;
 }
@@ -319,7 +330,7 @@ void ft_sess_close(struct se_session *se_sess)
                mutex_unlock(&ft_lport_lock);
                return;
        }
-       pr_debug("port_id %x\n", port_id);
+       TFC_SESS_DBG(sess->tport->lport, "port_id %x close session\n", port_id);
        ft_sess_unhash(sess);
        mutex_unlock(&ft_lport_lock);
        ft_close_sess(sess);
@@ -379,8 +390,13 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len,
                if (!(fcp_parm & FCP_SPPF_INIT_FCN))
                        return FC_SPP_RESP_CONF;
                sess = ft_sess_create(tport, rdata->ids.port_id, rdata);
-               if (!sess)
-                       return FC_SPP_RESP_RES;
+               if (IS_ERR(sess)) {
+                       if (PTR_ERR(sess) == -EACCES) {
+                               spp->spp_flags &= ~FC_SPP_EST_IMG_PAIR;
+                               return FC_SPP_RESP_CONF;
+                       } else
+                               return FC_SPP_RESP_RES;
+               }
                if (!sess->params)
                        rdata->prli_count++;
                sess->params = fcp_parm;
@@ -423,8 +439,8 @@ static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len,
        mutex_lock(&ft_lport_lock);
        ret = ft_prli_locked(rdata, spp_len, rspp, spp);
        mutex_unlock(&ft_lport_lock);
-       pr_debug("port_id %x flags %x ret %x\n",
-              rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret);
+       TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n",
+                    rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret);
        return ret;
 }
 
@@ -477,11 +493,11 @@ static void ft_recv(struct fc_lport *lport, struct fc_frame *fp)
        struct ft_sess *sess;
        u32 sid = fc_frame_sid(fp);
 
-       pr_debug("sid %x\n", sid);
+       TFC_SESS_DBG(lport, "recv sid %x\n", sid);
 
        sess = ft_sess_get(lport, sid);
        if (!sess) {
-               pr_debug("sid %x sess lookup failed\n", sid);
+               TFC_SESS_DBG(lport, "sid %x sess lookup failed\n", sid);
                /* TBD XXX - if FCP_CMND, send PRLO */
                fc_frame_free(fp);
                return;
index 9b4815e..19bf202 100644 (file)
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/acpi.h>
 #include <linux/thermal.h>
 #include <linux/pm.h>
 
 /* Intel PCH thermal Device IDs */
+#define PCH_THERMAL_DID_HSW_1  0x9C24 /* Haswell PCH */
+#define PCH_THERMAL_DID_HSW_2  0x8C24 /* Haswell PCH */
 #define PCH_THERMAL_DID_WPT    0x9CA4 /* Wildcat Point */
 #define PCH_THERMAL_DID_SKL    0x9D31 /* Skylake PCH */
 
@@ -66,9 +69,53 @@ struct pch_thermal_device {
        unsigned long crt_temp;
        int hot_trip_id;
        unsigned long hot_temp;
+       int psv_trip_id;
+       unsigned long psv_temp;
        bool bios_enabled;
 };
 
+#ifdef CONFIG_ACPI
+
+/*
+ * On some platforms, there is a companion ACPI device, which adds
+ * passive trip temperature using _PSV method. There is no specific
+ * passive temperature setting in MMIO interface of this PCI device.
+ */
+static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
+                                     int *nr_trips)
+{
+       struct acpi_device *adev;
+
+       ptd->psv_trip_id = -1;
+
+       adev = ACPI_COMPANION(&ptd->pdev->dev);
+       if (adev) {
+               unsigned long long r;
+               acpi_status status;
+
+               status = acpi_evaluate_integer(adev->handle, "_PSV", NULL,
+                                              &r);
+               if (ACPI_SUCCESS(status)) {
+                       unsigned long trip_temp;
+
+                       trip_temp = DECI_KELVIN_TO_MILLICELSIUS(r);
+                       if (trip_temp) {
+                               ptd->psv_temp = trip_temp;
+                               ptd->psv_trip_id = *nr_trips;
+                               ++(*nr_trips);
+                       }
+               }
+       }
+}
+#else
+static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd,
+                                     int *nr_trips)
+{
+       ptd->psv_trip_id = -1;
+
+}
+#endif
+
 static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
 {
        u8 tsel;
@@ -119,6 +166,8 @@ read_trips:
                ++(*nr_trips);
        }
 
+       pch_wpt_add_acpi_psv_trip(ptd, nr_trips);
+
        return 0;
 }
 
@@ -194,6 +243,8 @@ static int pch_get_trip_type(struct thermal_zone_device *tzd, int trip,
                *type = THERMAL_TRIP_CRITICAL;
        else if (ptd->hot_trip_id == trip)
                *type = THERMAL_TRIP_HOT;
+       else if (ptd->psv_trip_id == trip)
+               *type = THERMAL_TRIP_PASSIVE;
        else
                return -EINVAL;
 
@@ -208,6 +259,8 @@ static int pch_get_trip_temp(struct thermal_zone_device *tzd, int trip, int *tem
                *temp = ptd->crt_temp;
        else if (ptd->hot_trip_id == trip)
                *temp = ptd->hot_temp;
+       else if (ptd->psv_trip_id == trip)
+               *temp = ptd->psv_temp;
        else
                return -EINVAL;
 
@@ -242,6 +295,11 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev,
                ptd->ops = &pch_dev_ops_wpt;
                dev_name = "pch_skylake";
                break;
+       case PCH_THERMAL_DID_HSW_1:
+       case PCH_THERMAL_DID_HSW_2:
+               ptd->ops = &pch_dev_ops_wpt;
+               dev_name = "pch_haswell";
+               break;
        default:
                dev_err(&pdev->dev, "unknown pch thermal device\n");
                return -ENODEV;
@@ -324,6 +382,8 @@ static int intel_pch_thermal_resume(struct device *device)
 static struct pci_device_id intel_pch_thermal_id[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_1) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_HSW_2) },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
index 0e4dc0a..7a22307 100644 (file)
@@ -669,20 +669,10 @@ static struct thermal_cooling_device_ops powerclamp_cooling_ops = {
        .set_cur_state = powerclamp_set_cur_state,
 };
 
-static const struct x86_cpu_id intel_powerclamp_ids[] __initconst = {
-       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_MWAIT },
-       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ARAT },
-       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_NONSTOP_TSC },
-       { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_CONSTANT_TSC},
-       {}
-};
-MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);
-
 static int __init powerclamp_probe(void)
 {
-       if (!x86_match_cpu(intel_powerclamp_ids)) {
-               pr_err("Intel powerclamp does not run on family %d model %d\n",
-                               boot_cpu_data.x86, boot_cpu_data.x86_model);
+       if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
+               pr_err("CPU does not support MWAIT");
                return -ENODEV;
        }
 
index 886fcf3..b992346 100644 (file)
@@ -213,7 +213,7 @@ static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
        struct pci_dev *pdev = to_pci_dev(port->dev);
        int ret;
 
-       ret = pci_alloc_irq_vectors(pdev, 1, 1, 0);
+       ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
        if (ret < 0)
                return ret;
 
index 1bfb6fd..1731b98 100644 (file)
@@ -83,7 +83,8 @@ static const struct serial8250_config uart_config[] = {
                .name           = "16550A",
                .fifo_size      = 16,
                .tx_loadsz      = 16,
-               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+                                 UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
                .rxtrig_bytes   = {1, 4, 8, 14},
                .flags          = UART_CAP_FIFO,
        },
index b8d9c8c..417d9e7 100644 (file)
@@ -99,7 +99,7 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
        case UART_LCR:
                valshift = UNIPHIER_UART_LCR_SHIFT;
                /* Divisor latch access bit does not exist. */
-               value &= ~(UART_LCR_DLAB << valshift);
+               value &= ~UART_LCR_DLAB;
                /* fall through */
        case UART_MCR:
                offset = UNIPHIER_UART_LCR_MCR;
@@ -199,7 +199,7 @@ static int uniphier_uart_probe(struct platform_device *pdev)
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
-               dev_err(dev, "failed to get memory resource");
+               dev_err(dev, "failed to get memory resource\n");
                return -EINVAL;
        }
 
index c783140..25c1d7b 100644 (file)
@@ -1625,6 +1625,7 @@ config SERIAL_SPRD_CONSOLE
 config SERIAL_STM32
        tristate "STMicroelectronics STM32 serial port support"
        select SERIAL_CORE
+       depends on HAS_DMA
        depends on ARM || COMPILE_TEST
        help
          This driver is for the on-chip Serial Controller on
index fd8aa1f..168b10c 100644 (file)
@@ -2132,11 +2132,29 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
                mode |= ATMEL_US_USMODE_RS485;
        } else if (termios->c_cflag & CRTSCTS) {
                /* RS232 with hardware handshake (RTS/CTS) */
-               if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) {
-                       dev_info(port->dev, "not enabling hardware flow control because DMA is used");
-                       termios->c_cflag &= ~CRTSCTS;
-               } else {
+               if (atmel_use_fifo(port) &&
+                   !mctrl_gpio_to_gpiod(atmel_port->gpios, UART_GPIO_CTS)) {
+                       /*
+                        * with ATMEL_US_USMODE_HWHS set, the controller will
+                        * be able to drive the RTS pin high/low when the RX
+                        * FIFO is above RXFTHRES/below RXFTHRES2.
+                        * It will also disable the transmitter when the CTS
+                        * pin is high.
+                        * This mode is not activated if CTS pin is a GPIO
+                        * because in this case, the transmitter is always
+                        * disabled (there must be an internal pull-up
+                        * responsible for this behaviour).
+                        * If the RTS pin is a GPIO, the controller won't be
+                        * able to drive it according to the FIFO thresholds,
+                        * but it will be handled by the driver.
+                        */
                        mode |= ATMEL_US_USMODE_HWHS;
+               } else {
+                       /*
+                        * For platforms without FIFO, the flow control is
+                        * handled by the driver.
+                        */
+                       mode |= ATMEL_US_USMODE_NORMAL;
                }
        } else {
                /* RS232 without hadware handshake */
index de9d510..76103f2 100644 (file)
@@ -328,7 +328,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
 
        sport->dma_tx_bytes = uart_circ_chars_pending(xmit);
 
-       if (xmit->tail < xmit->head) {
+       if (xmit->tail < xmit->head || xmit->head == 0) {
                sport->dma_tx_nents = 1;
                sg_init_one(sgl, xmit->buf + xmit->tail, sport->dma_tx_bytes);
        } else {
@@ -359,7 +359,6 @@ static void lpuart_dma_tx(struct lpuart_port *sport)
        sport->dma_tx_in_progress = true;
        sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc);
        dma_async_issue_pending(sport->dma_tx_chan);
-
 }
 
 static void lpuart_dma_tx_complete(void *arg)
index d391650..42caccb 100644 (file)
@@ -419,6 +419,7 @@ static struct dmi_system_id pch_uart_dmi_table[] = {
                },
                (void *)MINNOW_UARTCLK,
        },
+       { }
 };
 
 /* Return UART clock, checking for board specific clocks. */
index 2675792..fb06725 100644 (file)
@@ -1130,9 +1130,13 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
 {
        struct sc16is7xx_port *s = gpiochip_get_data(chip);
        struct uart_port *port = &s->p[0].port;
+       u8 state = sc16is7xx_port_read(port, SC16IS7XX_IOSTATE_REG);
 
-       sc16is7xx_port_update(port, SC16IS7XX_IOSTATE_REG, BIT(offset),
-                             val ? BIT(offset) : 0);
+       if (val)
+               state |= BIT(offset);
+       else
+               state &= ~BIT(offset);
+       sc16is7xx_port_write(port, SC16IS7XX_IOSTATE_REG, state);
        sc16is7xx_port_update(port, SC16IS7XX_IODIR_REG, BIT(offset),
                              BIT(offset));
 
index 6e4f636..f2303f3 100644 (file)
@@ -111,7 +111,7 @@ void uart_write_wakeup(struct uart_port *port)
         * closed.  No cookie for you.
         */
        BUG_ON(!state);
-       tty_wakeup(state->port.tty);
+       tty_port_tty_wakeup(&state->port);
 }
 
 static void uart_stop(struct tty_struct *tty)
@@ -632,7 +632,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
        if (port->ops->flush_buffer)
                port->ops->flush_buffer(port);
        uart_port_unlock(port, flags);
-       tty_wakeup(tty);
+       tty_port_tty_wakeup(&state->port);
 }
 
 /*
@@ -2746,8 +2746,6 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
        uport->cons = drv->cons;
        uport->minor = drv->tty_driver->minor_start + uport->line;
 
-       port->console = uart_console(uport);
-
        /*
         * If this port is a console, then the spinlock is already
         * initialised.
@@ -2761,6 +2759,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 
        uart_configure_port(drv, state, uport);
 
+       port->console = uart_console(uport);
+
        num_groups = 2;
        if (uport->attr_group)
                num_groups++;
index 41d9749..cd97ceb 100644 (file)
@@ -31,7 +31,7 @@ struct stm32_usart_info {
        struct stm32_usart_config cfg;
 };
 
-#define UNDEF_REG ~0
+#define UNDEF_REG 0xff
 
 /* Register offsets */
 struct stm32_usart_info stm32f4_info = {
index f37edaa..dd4c02f 100644 (file)
@@ -1200,6 +1200,7 @@ static int __init cdns_early_console_setup(struct earlycon_device *device,
 OF_EARLYCON_DECLARE(cdns, "xlnx,xuartps", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup);
 OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup);
+OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup);
 
 /**
  * cdns_uart_console_write - perform write operation
@@ -1438,6 +1439,7 @@ static const struct of_device_id cdns_uart_of_match[] = {
        { .compatible = "xlnx,xuartps", },
        { .compatible = "cdns,uart-r1p8", },
        { .compatible = "cdns,uart-r1p12", .data = &zynqmp_uart_def },
+       { .compatible = "xlnx,zynqmp-uart", .data = &zynqmp_uart_def },
        {}
 };
 MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
index 06fb39c..8c3bf3d 100644 (file)
@@ -870,10 +870,15 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
                return 0;
 
+       if (new_screen_size > (4 << 20))
+               return -EINVAL;
        newscreen = kmalloc(new_screen_size, GFP_USER);
        if (!newscreen)
                return -ENOMEM;
 
+       if (vc == sel_cons)
+               clear_selection();
+
        old_rows = vc->vc_rows;
        old_row_size = vc->vc_size_row;
 
@@ -1176,7 +1181,7 @@ static void csi_J(struct vc_data *vc, int vpar)
                        break;
                case 3: /* erase scroll-back buffer (and whole display) */
                        scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
-                                   vc->vc_screenbuf_size >> 1);
+                                   vc->vc_screenbuf_size);
                        set_origin(vc);
                        if (con_is_visible(vc))
                                update_screen(vc);
index 96ae695..111b0e0 100644 (file)
@@ -188,6 +188,8 @@ static void host_stop(struct ci_hdrc *ci)
 
        if (hcd) {
                usb_remove_hcd(hcd);
+               ci->role = CI_ROLE_END;
+               synchronize_irq(ci->irq);
                usb_put_hcd(hcd);
                if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
                        (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
index fa9b26b..4c0fa0b 100644 (file)
@@ -463,9 +463,18 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg)
  */
 void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
 {
+       bool ret;
+
        switch (hsotg->dr_mode) {
        case USB_DR_MODE_HOST:
-               dwc2_force_mode(hsotg, true);
+               ret = dwc2_force_mode(hsotg, true);
+               /*
+                * NOTE: This is required for some rockchip soc based
+                * platforms on their host-only dwc2.
+                */
+               if (!ret)
+                       msleep(50);
+
                break;
        case USB_DR_MODE_PERIPHERAL:
                dwc2_force_mode(hsotg, false);
index aad4107..2a21a04 100644 (file)
@@ -259,6 +259,13 @@ enum dwc2_lx_state {
        DWC2_L3,        /* Off state */
 };
 
+/*
+ * Gadget periodic tx fifo sizes as used by legacy driver
+ * EP0 is not included
+ */
+#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
+                                          768, 0, 0, 0, 0, 0, 0, 0}
+
 /* Gadget ep0 states */
 enum dwc2_ep0_state {
        DWC2_EP0_SETUP,
index 4cd6403..24fbebc 100644 (file)
@@ -186,10 +186,9 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
  */
 static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
 {
-       unsigned int fifo;
+       unsigned int ep;
        unsigned int addr;
        int timeout;
-       u32 dptxfsizn;
        u32 val;
 
        /* Reset fifo map if not correctly cleared during previous session */
@@ -217,16 +216,16 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
         * them to endpoints dynamically according to maxpacket size value of
         * given endpoint.
         */
-       for (fifo = 1; fifo < MAX_EPS_CHANNELS; fifo++) {
-               dptxfsizn = dwc2_readl(hsotg->regs + DPTXFSIZN(fifo));
-
-               val = (dptxfsizn & FIFOSIZE_DEPTH_MASK) | addr;
-               addr += dptxfsizn >> FIFOSIZE_DEPTH_SHIFT;
-
-               if (addr > hsotg->fifo_mem)
-                       break;
+       for (ep = 1; ep < MAX_EPS_CHANNELS; ep++) {
+               if (!hsotg->g_tx_fifo_sz[ep])
+                       continue;
+               val = addr;
+               val |= hsotg->g_tx_fifo_sz[ep] << FIFOSIZE_DEPTH_SHIFT;
+               WARN_ONCE(addr + hsotg->g_tx_fifo_sz[ep] > hsotg->fifo_mem,
+                         "insufficient fifo memory");
+               addr += hsotg->g_tx_fifo_sz[ep];
 
-               dwc2_writel(val, hsotg->regs + DPTXFSIZN(fifo));
+               dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
        }
 
        /*
@@ -3807,10 +3806,36 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
 static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg)
 {
        struct device_node *np = hsotg->dev->of_node;
+       u32 len = 0;
+       u32 i = 0;
 
        /* Enable dma if requested in device tree */
        hsotg->g_using_dma = of_property_read_bool(np, "g-use-dma");
 
+       /*
+       * Register TX periodic fifo size per endpoint.
+       * EP0 is excluded since it has no fifo configuration.
+       */
+       if (!of_find_property(np, "g-tx-fifo-size", &len))
+               goto rx_fifo;
+
+       len /= sizeof(u32);
+
+       /* Read tx fifo sizes other than ep0 */
+       if (of_property_read_u32_array(np, "g-tx-fifo-size",
+                                               &hsotg->g_tx_fifo_sz[1], len))
+               goto rx_fifo;
+
+       /* Add ep0 */
+       len++;
+
+       /* Make remaining TX fifos unavailable */
+       if (len < MAX_EPS_CHANNELS) {
+               for (i = len; i < MAX_EPS_CHANNELS; i++)
+                       hsotg->g_tx_fifo_sz[i] = 0;
+       }
+
+rx_fifo:
        /* Register RX fifo size */
        of_property_read_u32(np, "g-rx-fifo-size", &hsotg->g_rx_fifo_sz);
 
@@ -3832,10 +3857,13 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
        struct device *dev = hsotg->dev;
        int epnum;
        int ret;
+       int i;
+       u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
 
        /* Initialize to legacy fifo configuration values */
        hsotg->g_rx_fifo_sz = 2048;
        hsotg->g_np_g_tx_fifo_sz = 1024;
+       memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo));
        /* Device tree specific probe */
        dwc2_hsotg_of_probe(hsotg);
 
@@ -3853,6 +3881,9 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
        dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n",
                                                hsotg->g_np_g_tx_fifo_sz);
        dev_dbg(dev, "RXFIFO size: %d\n", hsotg->g_rx_fifo_sz);
+       for (i = 0; i < MAX_EPS_CHANNELS; i++)
+               dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i,
+                                               hsotg->g_tx_fifo_sz[i]);
 
        hsotg->gadget.max_speed = USB_SPEED_HIGH;
        hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
index 07cc892..1dfa56a 100644 (file)
@@ -783,6 +783,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
                req->trb = trb;
                req->trb_dma = dwc3_trb_dma_offset(dep, trb);
                req->first_trb_index = dep->trb_enqueue;
+               dep->queued_requests++;
        }
 
        dwc3_ep_inc_enq(dep);
@@ -833,8 +834,6 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 
        trb->ctrl |= DWC3_TRB_CTRL_HWO;
 
-       dep->queued_requests++;
-
        trace_dwc3_prepare_trb(dep, trb);
 }
 
@@ -1074,9 +1073,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
        list_add_tail(&req->list, &dep->pending_list);
 
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
-                       dep->flags & DWC3_EP_PENDING_REQUEST) {
-               if (list_empty(&dep->started_list)) {
+       /*
+        * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
+        * wait for a XferNotReady event so we will know what's the current
+        * (micro-)frame number.
+        *
+        * Without this trick, we are very, very likely gonna get Bus Expiry
+        * errors which will force us issue EndTransfer command.
+        */
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+               if ((dep->flags & DWC3_EP_PENDING_REQUEST) &&
+                               list_empty(&dep->started_list)) {
                        dwc3_stop_active_transfer(dwc, dep->number, true);
                        dep->flags = DWC3_EP_ENABLED;
                }
@@ -1861,8 +1868,11 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
        unsigned int            s_pkt = 0;
        unsigned int            trb_status;
 
-       dep->queued_requests--;
        dwc3_ep_inc_deq(dep);
+
+       if (req->trb == trb)
+               dep->queued_requests--;
+
        trace_dwc3_complete_trb(dep, trb);
 
        /*
@@ -2980,7 +2990,7 @@ err3:
        kfree(dwc->setup_buf);
 
 err2:
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
                        dwc->ep0_trb, dwc->ep0_trb_addr);
 
 err1:
@@ -3005,7 +3015,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
        kfree(dwc->setup_buf);
        kfree(dwc->zlp_buf);
 
-       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+       dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
                        dwc->ep0_trb, dwc->ep0_trb_addr);
 
        dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
index 54ad100..e40d47d 100644 (file)
@@ -136,8 +136,60 @@ struct ffs_epfile {
        /*
         * Buffer for holding data from partial reads which may happen since
         * we’re rounding user read requests to a multiple of a max packet size.
+        *
+        * The pointer is initialised with NULL value and may be set by
+        * __ffs_epfile_read_data function to point to a temporary buffer.
+        *
+        * In normal operation, calls to __ffs_epfile_read_buffered will consume
+        * data from said buffer and eventually free it.  Importantly, while the
+        * function is using the buffer, it sets the pointer to NULL.  This is
+        * all right since __ffs_epfile_read_data and __ffs_epfile_read_buffered
+        * can never run concurrently (they are synchronised by epfile->mutex)
+        * so the latter will not assign a new value to the pointer.
+        *
+        * Meanwhile ffs_func_eps_disable frees the buffer (if the pointer is
+        * valid) and sets the pointer to READ_BUFFER_DROP value.  This special
+        * value is crux of the synchronisation between ffs_func_eps_disable and
+        * __ffs_epfile_read_data.
+        *
+        * Once __ffs_epfile_read_data is about to finish it will try to set the
+        * pointer back to its old value (as described above), but seeing as the
+        * pointer is not-NULL (namely READ_BUFFER_DROP) it will instead free
+        * the buffer.
+        *
+        * == State transitions ==
+        *
+        * â€¢ ptr == NULL:  (initial state)
+        *   â—¦ __ffs_epfile_read_buffer_free: go to ptr == DROP
+        *   â—¦ __ffs_epfile_read_buffered:    nop
+        *   â—¦ __ffs_epfile_read_data allocates temp buffer: go to ptr == buf
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == DROP:
+        *   â—¦ __ffs_epfile_read_buffer_free: nop
+        *   â—¦ __ffs_epfile_read_buffered:    go to ptr == NULL
+        *   â—¦ __ffs_epfile_read_data allocates temp buffer: free buf, nop
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == buf:
+        *   â—¦ __ffs_epfile_read_buffer_free: free buf, go to ptr == DROP
+        *   â—¦ __ffs_epfile_read_buffered:    go to ptr == NULL and reading
+        *   â—¦ __ffs_epfile_read_data:        n/a, __ffs_epfile_read_buffered
+        *                                    is always called first
+        *   â—¦ reading finishes:              n/a, not in â€˜and reading’ state
+        * â€¢ ptr == NULL and reading:
+        *   â—¦ __ffs_epfile_read_buffer_free: go to ptr == DROP and reading
+        *   â—¦ __ffs_epfile_read_buffered:    n/a, mutex is held
+        *   â—¦ __ffs_epfile_read_data:        n/a, mutex is held
+        *   â—¦ reading finishes and â€¦
+        *     â€¦ all data read:               free buf, go to ptr == NULL
+        *     â€¦ otherwise:                   go to ptr == buf and reading
+        * â€¢ ptr == DROP and reading:
+        *   â—¦ __ffs_epfile_read_buffer_free: nop
+        *   â—¦ __ffs_epfile_read_buffered:    n/a, mutex is held
+        *   â—¦ __ffs_epfile_read_data:        n/a, mutex is held
+        *   â—¦ reading finishes:              free buf, go to ptr == DROP
         */
-       struct ffs_buffer               *read_buffer;   /* P: epfile->mutex */
+       struct ffs_buffer               *read_buffer;
+#define READ_BUFFER_DROP ((struct ffs_buffer *)ERR_PTR(-ESHUTDOWN))
 
        char                            name[5];
 
@@ -736,25 +788,47 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
        schedule_work(&io_data->work);
 }
 
+static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
+{
+       /*
+        * See comment in struct ffs_epfile for full read_buffer pointer
+        * synchronisation story.
+        */
+       struct ffs_buffer *buf = xchg(&epfile->read_buffer, READ_BUFFER_DROP);
+       if (buf && buf != READ_BUFFER_DROP)
+               kfree(buf);
+}
+
 /* Assumes epfile->mutex is held. */
 static ssize_t __ffs_epfile_read_buffered(struct ffs_epfile *epfile,
                                          struct iov_iter *iter)
 {
-       struct ffs_buffer *buf = epfile->read_buffer;
+       /*
+        * Null out epfile->read_buffer so ffs_func_eps_disable does not free
+        * the buffer while we are using it.  See comment in struct ffs_epfile
+        * for full read_buffer pointer synchronisation story.
+        */
+       struct ffs_buffer *buf = xchg(&epfile->read_buffer, NULL);
        ssize_t ret;
-       if (!buf)
+       if (!buf || buf == READ_BUFFER_DROP)
                return 0;
 
        ret = copy_to_iter(buf->data, buf->length, iter);
        if (buf->length == ret) {
                kfree(buf);
-               epfile->read_buffer = NULL;
-       } else if (unlikely(iov_iter_count(iter))) {
+               return ret;
+       }
+
+       if (unlikely(iov_iter_count(iter))) {
                ret = -EFAULT;
        } else {
                buf->length -= ret;
                buf->data += ret;
        }
+
+       if (cmpxchg(&epfile->read_buffer, NULL, buf))
+               kfree(buf);
+
        return ret;
 }
 
@@ -783,7 +857,15 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
        buf->length = data_len;
        buf->data = buf->storage;
        memcpy(buf->storage, data + ret, data_len);
-       epfile->read_buffer = buf;
+
+       /*
+        * At this point read_buffer is NULL or READ_BUFFER_DROP (if
+        * ffs_func_eps_disable has been called in the meanwhile).  See comment
+        * in struct ffs_epfile for full read_buffer pointer synchronisation
+        * story.
+        */
+       if (unlikely(cmpxchg(&epfile->read_buffer, NULL, buf)))
+               kfree(buf);
 
        return ret;
 }
@@ -1097,8 +1179,7 @@ ffs_epfile_release(struct inode *inode, struct file *file)
 
        ENTER();
 
-       kfree(epfile->read_buffer);
-       epfile->read_buffer = NULL;
+       __ffs_epfile_read_buffer_free(epfile);
        ffs_data_closed(epfile->ffs);
 
        return 0;
@@ -1724,24 +1805,20 @@ static void ffs_func_eps_disable(struct ffs_function *func)
        unsigned count            = func->ffs->eps_count;
        unsigned long flags;
 
+       spin_lock_irqsave(&func->ffs->eps_lock, flags);
        do {
-               if (epfile)
-                       mutex_lock(&epfile->mutex);
-               spin_lock_irqsave(&func->ffs->eps_lock, flags);
                /* pending requests get nuked */
                if (likely(ep->ep))
                        usb_ep_disable(ep->ep);
                ++ep;
-               spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 
                if (epfile) {
                        epfile->ep = NULL;
-                       kfree(epfile->read_buffer);
-                       epfile->read_buffer = NULL;
-                       mutex_unlock(&epfile->mutex);
+                       __ffs_epfile_read_buffer_free(epfile);
                        ++epfile;
                }
        } while (--count);
+       spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 }
 
 static int ffs_func_eps_enable(struct ffs_function *func)
index 9c8c9ed..fe18116 100644 (file)
@@ -590,8 +590,9 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
 
        /* throttle high/super speed IRQ rate back slightly */
        if (gadget_is_dualspeed(dev->gadget))
-               req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH ||
-                                    dev->gadget->speed == USB_SPEED_SUPER)
+               req->no_interrupt = (((dev->gadget->speed == USB_SPEED_HIGH ||
+                                      dev->gadget->speed == USB_SPEED_SUPER)) &&
+                                       !list_empty(&dev->tx_reqs))
                        ? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0)
                        : 0;
 
index bb1f6c8..45bc997 100644 (file)
@@ -1978,7 +1978,7 @@ 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 = name;
+               ep->ep.name = kasprintf(GFP_KERNEL, "ep%d", ep->index);
 
                ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
                ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
index 876dca4..a268d9e 100644 (file)
@@ -39,7 +39,7 @@
 
 #define DRIVER_DESC "EHCI generic platform driver"
 #define EHCI_MAX_CLKS 4
-#define EHCI_MAX_RSTS 3
+#define EHCI_MAX_RSTS 4
 #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
 
 struct ehci_platform_priv {
index 5b5880c..b38a228 100644 (file)
@@ -221,6 +221,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
        ohci->num_ports = board->ports;
        at91_start_hc(pdev);
 
+       /*
+        * The RemoteWakeupConnected bit has to be set explicitly
+        * before calling ohci_run. The reset value of this bit is 0.
+        */
+       ohci->hc_control = OHCI_CTRL_RWC;
+
        retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval == 0) {
                device_wakeup_enable(hcd->self.controller);
@@ -677,9 +683,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
         * REVISIT: some boards will be able to turn VBUS off...
         */
        if (!ohci_at91->wakeup) {
-               ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
-               ohci->hc_control &= OHCI_CTRL_RWC;
-               ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
                ohci->rh_state = OHCI_RH_HALTED;
 
                /* flush the writes */
index 1700908..86612ac 100644 (file)
@@ -72,7 +72,7 @@
 static const char      hcd_name [] = "ohci_hcd";
 
 #define        STATECHANGE_DELAY       msecs_to_jiffies(300)
-#define        IO_WATCHDOG_DELAY       msecs_to_jiffies(250)
+#define        IO_WATCHDOG_DELAY       msecs_to_jiffies(275)
 
 #include "ohci.h"
 #include "pci-quirks.h"
index 730b9fd..0ef1690 100644 (file)
@@ -1166,7 +1166,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_RESUME);
                                spin_unlock_irqrestore(&xhci->lock, flags);
-                               msleep(20);
+                               msleep(USB_RESUME_TIMEOUT);
                                spin_lock_irqsave(&xhci->lock, flags);
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_U0);
@@ -1355,6 +1355,35 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
        return 0;
 }
 
+/*
+ * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3.
+ * warm reset a USB3 device stuck in polling or compliance mode after resume.
+ * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8
+ */
+static bool xhci_port_missing_cas_quirk(int port_index,
+                                            __le32 __iomem **port_array)
+{
+       u32 portsc;
+
+       portsc = readl(port_array[port_index]);
+
+       /* if any of these are set we are not stuck */
+       if (portsc & (PORT_CONNECT | PORT_CAS))
+               return false;
+
+       if (((portsc & PORT_PLS_MASK) != XDEV_POLLING) &&
+           ((portsc & PORT_PLS_MASK) != XDEV_COMP_MODE))
+               return false;
+
+       /* clear wakeup/change bits, and do a warm port reset */
+       portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
+       portsc |= PORT_WR;
+       writel(portsc, port_array[port_index]);
+       /* flush write */
+       readl(port_array[port_index]);
+       return true;
+}
+
 int xhci_bus_resume(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -1392,6 +1421,14 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                u32 temp;
 
                temp = readl(port_array[port_index]);
+
+               /* warm reset CAS limited ports stuck in polling/compliance */
+               if ((xhci->quirks & XHCI_MISSING_CAS) &&
+                   (hcd->speed >= HCD_USB3) &&
+                   xhci_port_missing_cas_quirk(port_index, port_array)) {
+                       xhci_dbg(xhci, "reset stuck port %d\n", port_index);
+                       continue;
+               }
                if (DEV_SUPERSPEED_ANY(temp))
                        temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
                else
@@ -1410,7 +1447,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
        if (need_usb2_u3_exit) {
                spin_unlock_irqrestore(&xhci->lock, flags);
-               msleep(20);
+               msleep(USB_RESUME_TIMEOUT);
                spin_lock_irqsave(&xhci->lock, flags);
        }
 
index d7b0f97..e96ae80 100644 (file)
 
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI     0x8c31
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI  0x9c31
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI       0x9cb1
 #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI            0x22b5
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI                0xa12f
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI       0x9d2f
 #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI             0x0aa8
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI             0x1aa8
+#define PCI_DEVICE_ID_INTEL_APL_XHCI                   0x5aa8
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -153,7 +155,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-               pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
+               (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI)) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
                xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
@@ -169,6 +172,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
                xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
        }
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+           (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+            pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
+               xhci->quirks |= XHCI_MISSING_CAS;
+
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_EJ168) {
                xhci->quirks |= XHCI_RESET_ON_RESUME;
index b2c1dc5..f945380 100644 (file)
@@ -314,6 +314,8 @@ struct xhci_op_regs {
 #define XDEV_U2                (0x2 << 5)
 #define XDEV_U3                (0x3 << 5)
 #define XDEV_INACTIVE  (0x6 << 5)
+#define XDEV_POLLING   (0x7 << 5)
+#define XDEV_COMP_MODE  (0xa << 5)
 #define XDEV_RESUME    (0xf << 5)
 /* true: port has power (see HCC_PPC) */
 #define PORT_POWER     (1 << 9)
@@ -1653,6 +1655,7 @@ struct xhci_hcd {
 #define XHCI_MTK_HOST          (1 << 21)
 #define XHCI_SSIC_PORT_UNUSED  (1 << 22)
 #define XHCI_NO_64BIT_SUPPORT  (1 << 23)
+#define XHCI_MISSING_CAS       (1 << 24)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
index bff4869..4042ea0 100644 (file)
@@ -1255,6 +1255,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 
        map_dma_buffer(request, musb, musb_ep);
 
+       pm_runtime_get_sync(musb->controller);
        spin_lock_irqsave(&musb->lock, lockflags);
 
        /* don't queue if the ep is down */
@@ -1275,6 +1276,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 
 unlock:
        spin_unlock_irqrestore(&musb->lock, lockflags);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
+
        return status;
 }
 
index 1ab6973..cc12254 100644 (file)
@@ -287,6 +287,7 @@ static int omap2430_musb_init(struct musb *musb)
        }
        musb->isr = omap2430_musb_interrupt;
        phy_init(musb->phy);
+       phy_power_on(musb->phy);
 
        l = musb_readl(musb->mregs, OTG_INTERFSEL);
 
@@ -323,8 +324,6 @@ static void omap2430_musb_enable(struct musb *musb)
        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
        struct omap_musb_board_data *data = pdata->board_data;
 
-       if (!WARN_ON(!musb->phy))
-               phy_power_on(musb->phy);
 
        switch (glue->status) {
 
@@ -361,9 +360,6 @@ static void omap2430_musb_disable(struct musb *musb)
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
-       if (!WARN_ON(!musb->phy))
-               phy_power_off(musb->phy);
-
        if (glue->status != MUSB_UNKNOWN)
                omap_control_usb_set_mode(glue->control_otghs,
                        USB_MODE_DISCONNECT);
@@ -375,6 +371,7 @@ static int omap2430_musb_exit(struct musb *musb)
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
        omap2430_low_level_exit(musb);
+       phy_power_off(musb->phy);
        phy_exit(musb->phy);
        musb->phy = NULL;
        cancel_work_sync(&glue->omap_musb_mailbox_work);
index 1d70add..d544b33 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/delay.h>
 #include <linux/io.h>
 #include "common.h"
 #include "rcar3.h"
@@ -35,10 +36,13 @@ static int usbhs_rcar3_power_ctrl(struct platform_device *pdev,
 
        usbhs_write32(priv, UGCTRL2, UGCTRL2_RESERVED_3 | UGCTRL2_USB0SEL_OTG);
 
-       if (enable)
+       if (enable) {
                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM);
-       else
+               /* The controller on R-Car Gen3 needs to wait up to 45 usec */
+               udelay(45);
+       } else {
                usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0);
+       }
 
        return 0;
 }
index 54a4de0..f61477b 100644 (file)
@@ -1077,7 +1077,9 @@ static int cp210x_tiocmget(struct tty_struct *tty)
        u8 control;
        int result;
 
-       cp210x_read_u8_reg(port, CP210X_GET_MDMSTS, &control);
+       result = cp210x_read_u8_reg(port, CP210X_GET_MDMSTS, &control);
+       if (result)
+               return result;
 
        result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
                |((control & CONTROL_RTS) ? TIOCM_RTS : 0)
index b2d767e..0ff7f38 100644 (file)
@@ -986,7 +986,8 @@ static const struct usb_device_id id_table_combined[] = {
        /* ekey Devices */
        { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
        /* Infineon Devices */
-       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC1798_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_TC2X7_PID, 1) },
        /* GE Healthcare devices */
        { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
        /* Active Research (Actisense) devices */
index f87a938..21011c0 100644 (file)
 /*
  * Infineon Technologies
  */
-#define INFINEON_VID           0x058b
-#define INFINEON_TRIBOARD_PID  0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_VID                   0x058b
+#define INFINEON_TRIBOARD_TC1798_PID   0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */
+#define INFINEON_TRIBOARD_TC2X7_PID    0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */
 
 /*
  * Acton Research Corp.
index d213cf4..4a037b4 100644 (file)
@@ -1078,7 +1078,8 @@ static int usb_serial_probe(struct usb_interface *interface,
 
        serial->disconnected = 0;
 
-       usb_serial_console_init(serial->port[0]->minor);
+       if (num_ports > 0)
+               usb_serial_console_init(serial->port[0]->minor);
 exit:
        module_put(type->driver.owner);
        return 0;
index 79b2b62..79451f7 100644 (file)
@@ -133,6 +133,13 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
                bo[itr] = bi1[itr] ^ bi2[itr];
 }
 
+/* Scratch space for MAC calculations. */
+struct wusb_mac_scratch {
+       struct aes_ccm_b0 b0;
+       struct aes_ccm_b1 b1;
+       struct aes_ccm_a ax;
+};
+
 /*
  * CC-MAC function WUSB1.0[6.5]
  *
@@ -197,16 +204,15 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2,
  *       what sg[4] is for. Maybe there is a smarter way to do this.
  */
 static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
-                       struct crypto_cipher *tfm_aes, void *mic,
+                       struct crypto_cipher *tfm_aes,
+                       struct wusb_mac_scratch *scratch,
+                       void *mic,
                        const struct aes_ccm_nonce *n,
                        const struct aes_ccm_label *a, const void *b,
                        size_t blen)
 {
        int result = 0;
        SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc);
-       struct aes_ccm_b0 b0;
-       struct aes_ccm_b1 b1;
-       struct aes_ccm_a ax;
        struct scatterlist sg[4], sg_dst;
        void *dst_buf;
        size_t dst_size;
@@ -218,16 +224,17 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * These checks should be compile time optimized out
         * ensure @a fills b1's mac_header and following fields
         */
-       WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la));
-       WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block));
-       WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block));
-       WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(*a) != sizeof(scratch->b1) - sizeof(scratch->b1.la));
+       WARN_ON(sizeof(scratch->b0) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(scratch->b1) != sizeof(struct aes_ccm_block));
+       WARN_ON(sizeof(scratch->ax) != sizeof(struct aes_ccm_block));
 
        result = -ENOMEM;
        zero_padding = blen % sizeof(struct aes_ccm_block);
        if (zero_padding)
                zero_padding = sizeof(struct aes_ccm_block) - zero_padding;
-       dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding;
+       dst_size = blen + sizeof(scratch->b0) + sizeof(scratch->b1) +
+               zero_padding;
        dst_buf = kzalloc(dst_size, GFP_KERNEL);
        if (!dst_buf)
                goto error_dst_buf;
@@ -235,9 +242,9 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
        memset(iv, 0, sizeof(iv));
 
        /* Setup B0 */
-       b0.flags = 0x59;        /* Format B0 */
-       b0.ccm_nonce = *n;
-       b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */
+       scratch->b0.flags = 0x59;       /* Format B0 */
+       scratch->b0.ccm_nonce = *n;
+       scratch->b0.lm = cpu_to_be16(0);        /* WUSB1.0[6.5] sez l(m) is 0 */
 
        /* Setup B1
         *
@@ -246,12 +253,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * 14'--after clarification, it means to use A's contents
         * for MAC Header, EO, sec reserved and padding.
         */
-       b1.la = cpu_to_be16(blen + 14);
-       memcpy(&b1.mac_header, a, sizeof(*a));
+       scratch->b1.la = cpu_to_be16(blen + 14);
+       memcpy(&scratch->b1.mac_header, a, sizeof(*a));
 
        sg_init_table(sg, ARRAY_SIZE(sg));
-       sg_set_buf(&sg[0], &b0, sizeof(b0));
-       sg_set_buf(&sg[1], &b1, sizeof(b1));
+       sg_set_buf(&sg[0], &scratch->b0, sizeof(scratch->b0));
+       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);
@@ -276,11 +283,12 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
         * POS Crypto API: size is assumed to be AES's block size.
         * Thanks for documenting it -- tip taken from airo.c
         */
-       ax.flags = 0x01;                /* as per WUSB 1.0 spec */
-       ax.ccm_nonce = *n;
-       ax.counter = 0;
-       crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax);
-       bytewise_xor(mic, &ax, iv, 8);
+       scratch->ax.flags = 0x01;               /* as per WUSB 1.0 spec */
+       scratch->ax.ccm_nonce = *n;
+       scratch->ax.counter = 0;
+       crypto_cipher_encrypt_one(tfm_aes, (void *)&scratch->ax,
+                                 (void *)&scratch->ax);
+       bytewise_xor(mic, &scratch->ax, iv, 8);
        result = 8;
 error_cbc_crypt:
        kfree(dst_buf);
@@ -303,6 +311,7 @@ ssize_t wusb_prf(void *out, size_t out_size,
        struct aes_ccm_nonce n = *_n;
        struct crypto_skcipher *tfm_cbc;
        struct crypto_cipher *tfm_aes;
+       struct wusb_mac_scratch *scratch;
        u64 sfn = 0;
        __le64 sfn_le;
 
@@ -329,17 +338,25 @@ ssize_t wusb_prf(void *out, size_t out_size,
                printk(KERN_ERR "E: can't set AES key: %d\n", (int)result);
                goto error_setkey_aes;
        }
+       scratch = kmalloc(sizeof(*scratch), GFP_KERNEL);
+       if (!scratch) {
+               result = -ENOMEM;
+               goto error_alloc_scratch;
+       }
 
        for (bitr = 0; bitr < (len + 63) / 64; bitr++) {
                sfn_le = cpu_to_le64(sfn++);
                memcpy(&n.sfn, &sfn_le, sizeof(n.sfn)); /* n.sfn++... */
-               result = wusb_ccm_mac(tfm_cbc, tfm_aes, out + bytes,
+               result = wusb_ccm_mac(tfm_cbc, tfm_aes, scratch, out + bytes,
                                      &n, a, b, blen);
                if (result < 0)
                        goto error_ccm_mac;
                bytes += result;
        }
        result = bytes;
+
+       kfree(scratch);
+error_alloc_scratch:
 error_ccm_mac:
 error_setkey_aes:
        crypto_free_cipher(tfm_aes);
index 3b1ca44..a2564ab 100644 (file)
@@ -686,8 +686,8 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
        if (!pages)
                return -ENOMEM;
 
-       ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, WRITE,
-                       0, pages);
+       ret = get_user_pages_unlocked((unsigned long)buf, nr_pages, pages,
+                       FOLL_WRITE);
 
        if (ret < nr_pages) {
                nr_pages = ret;
index 60bdad3..150ce2a 100644 (file)
@@ -245,8 +245,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
        /* Get the physical addresses of the source buffer */
        down_read(&current->mm->mmap_sem);
        num_pinned = get_user_pages(param.local_vaddr - lb_offset,
-               num_pages, (param.source == -1) ? READ : WRITE,
-               0, pages, NULL);
+               num_pages, (param.source == -1) ? 0 : FOLL_WRITE,
+               pages, NULL);
        up_read(&current->mm->mmap_sem);
 
        if (num_pinned != num_pages) {
index 15b6407..bdbadaa 100644 (file)
@@ -156,12 +156,16 @@ size_t vme_get_size(struct vme_resource *resource)
        case VME_MASTER:
                retval = vme_master_get(resource, &enabled, &base, &size,
                        &aspace, &cycle, &dwidth);
+               if (retval)
+                       return 0;
 
                return size;
                break;
        case VME_SLAVE:
                retval = vme_slave_get(resource, &enabled, &base, &size,
                        &buf_base, &aspace, &cycle);
+               if (retval)
+                       return 0;
 
                return size;
                break;
index e473e3b..6d1fbda 100644 (file)
@@ -499,6 +499,10 @@ static int wdat_wdt_resume_noirq(struct device *dev)
                ret = wdat_wdt_enable_reboot(wdat);
                if (ret)
                        return ret;
+
+               ret = wdat_wdt_ping(&wdat->wdd);
+               if (ret)
+                       return ret;
        }
 
        return wdat_wdt_start(&wdat->wdd);
index e12bd36..26e5e85 100644 (file)
@@ -168,7 +168,9 @@ out:
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
 
 struct shutdown_handler {
-       const char *command;
+#define SHUTDOWN_CMD_SIZE 11
+       const char command[SHUTDOWN_CMD_SIZE];
+       bool flag;
        void (*cb)(void);
 };
 
@@ -206,22 +208,22 @@ static void do_reboot(void)
        ctrl_alt_del();
 }
 
+static struct shutdown_handler shutdown_handlers[] = {
+       { "poweroff",   true,   do_poweroff },
+       { "halt",       false,  do_poweroff },
+       { "reboot",     true,   do_reboot   },
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+       { "suspend",    true,   do_suspend  },
+#endif
+};
+
 static void shutdown_handler(struct xenbus_watch *watch,
                             const char **vec, unsigned int len)
 {
        char *str;
        struct xenbus_transaction xbt;
        int err;
-       static struct shutdown_handler handlers[] = {
-               { "poweroff",   do_poweroff },
-               { "halt",       do_poweroff },
-               { "reboot",     do_reboot   },
-#ifdef CONFIG_HIBERNATE_CALLBACKS
-               { "suspend",    do_suspend  },
-#endif
-               {NULL, NULL},
-       };
-       static struct shutdown_handler *handler;
+       int idx;
 
        if (shutting_down != SHUTDOWN_INVALID)
                return;
@@ -238,13 +240,13 @@ static void shutdown_handler(struct xenbus_watch *watch,
                return;
        }
 
-       for (handler = &handlers[0]; handler->command; handler++) {
-               if (strcmp(str, handler->command) == 0)
+       for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
+               if (strcmp(str, shutdown_handlers[idx].command) == 0)
                        break;
        }
 
        /* Only acknowledge commands which we are prepared to handle. */
-       if (handler->cb)
+       if (idx < ARRAY_SIZE(shutdown_handlers))
                xenbus_write(xbt, "control", "shutdown", "");
 
        err = xenbus_transaction_end(xbt, 0);
@@ -253,8 +255,8 @@ static void shutdown_handler(struct xenbus_watch *watch,
                goto again;
        }
 
-       if (handler->cb) {
-               handler->cb();
+       if (idx < ARRAY_SIZE(shutdown_handlers)) {
+               shutdown_handlers[idx].cb();
        } else {
                pr_info("Ignoring shutdown request: %s\n", str);
                shutting_down = SHUTDOWN_INVALID;
@@ -310,6 +312,9 @@ static struct notifier_block xen_reboot_nb = {
 static int setup_shutdown_watcher(void)
 {
        int err;
+       int idx;
+#define FEATURE_PATH_SIZE (SHUTDOWN_CMD_SIZE + sizeof("feature-"))
+       char node[FEATURE_PATH_SIZE];
 
        err = register_xenbus_watch(&shutdown_watch);
        if (err) {
@@ -326,6 +331,14 @@ static int setup_shutdown_watcher(void)
        }
 #endif
 
+       for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) {
+               if (!shutdown_handlers[idx].flag)
+                       continue;
+               snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
+                        shutdown_handlers[idx].command);
+               xenbus_printf(XBT_NIL, "control", node, "%u", 1);
+       }
+
        return 0;
 }
 
index c1010f0..1e8be12 100644 (file)
@@ -364,7 +364,7 @@ out:
 
 static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
 {
-       struct watch_adapter *watch, *tmp_watch;
+       struct watch_adapter *watch;
        char *path, *token;
        int err, rc;
        LIST_HEAD(staging_q);
@@ -399,7 +399,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
                }
                list_add(&watch->list, &u->watches);
        } else {
-               list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
+               list_for_each_entry(watch, &u->watches, list) {
                        if (!strcmp(watch->token, token) &&
                            !strcmp(watch->watch.node, path)) {
                                unregister_xenbus_watch(&watch->watch);
index 611a231..6d40a97 100644 (file)
@@ -335,7 +335,9 @@ static int backend_state;
 static void xenbus_reset_backend_state_changed(struct xenbus_watch *w,
                                        const char **v, unsigned int l)
 {
-       xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i", &backend_state);
+       if (xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i",
+                        &backend_state) != 1)
+               backend_state = XenbusStateUnknown;
        printk(KERN_DEBUG "XENBUS: backend %s %s\n",
                        v[XS_WATCH_PATH], xenbus_strstate(backend_state));
        wake_up(&backend_state_wq);
index 2037e7a..d764236 100644 (file)
@@ -91,11 +91,9 @@ static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
  */
 bool afs_cm_incoming_call(struct afs_call *call)
 {
-       u32 operation_id = ntohl(call->operation_ID);
+       _enter("{CB.OP %u}", call->operation_ID);
 
-       _enter("{CB.OP %u}", operation_id);
-
-       switch (operation_id) {
+       switch (call->operation_ID) {
        case CBCallBack:
                call->type = &afs_SRXCBCallBack;
                return true;
index 96f4d76..31c616a 100644 (file)
@@ -364,7 +364,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                        buffer = kmap(page);
                        ret = afs_extract_data(call, buffer,
                                               call->count, true);
-                       kunmap(buffer);
+                       kunmap(page);
                        if (ret < 0)
                                return ret;
                }
@@ -397,7 +397,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                page = call->reply3;
                buffer = kmap(page);
                memset(buffer + call->count, 0, PAGE_SIZE - call->count);
-               kunmap(buffer);
+               kunmap(page);
        }
 
        _leave(" = 0 [done]");
index 5497c84..535a38d 100644 (file)
@@ -112,7 +112,7 @@ struct afs_call {
        bool                    need_attention; /* T if RxRPC poked us */
        u16                     service_id;     /* RxRPC service ID to call */
        __be16                  port;           /* target UDP port */
-       __be32                  operation_ID;   /* operation ID for an incoming call */
+       u32                     operation_ID;   /* operation ID for an incoming call */
        u32                     count;          /* count for use in unmarshalling */
        __be32                  tmp;            /* place to extract temporary data */
        afs_dataversion_t       store_version;  /* updated version expected from store */
index 477928b..25f05a8 100644 (file)
@@ -676,10 +676,11 @@ static int afs_deliver_cm_op_id(struct afs_call *call)
        ASSERTCMP(call->offset, <, 4);
 
        /* the operation ID forms the first four bytes of the request data */
-       ret = afs_extract_data(call, &call->operation_ID, 4, true);
+       ret = afs_extract_data(call, &call->tmp, 4, true);
        if (ret < 0)
                return ret;
 
+       call->operation_ID = ntohl(call->tmp);
        call->state = AFS_CALL_AWAIT_REQUEST;
        call->offset = 0;
 
index ccc70d9..d4d8b7e 100644 (file)
@@ -698,7 +698,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 
                        ret = btrfs_map_bio(root, comp_bio, mirror_num, 0);
                        if (ret) {
-                               bio->bi_error = ret;
+                               comp_bio->bi_error = ret;
                                bio_endio(comp_bio);
                        }
 
@@ -728,7 +728,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 
        ret = btrfs_map_bio(root, comp_bio, mirror_num, 0);
        if (ret) {
-               bio->bi_error = ret;
+               comp_bio->bi_error = ret;
                bio_endio(comp_bio);
        }
 
index 01bc36c..71261b4 100644 (file)
@@ -5805,6 +5805,64 @@ static int changed_extent(struct send_ctx *sctx,
        int ret = 0;
 
        if (sctx->cur_ino != sctx->cmp_key->objectid) {
+
+               if (result == BTRFS_COMPARE_TREE_CHANGED) {
+                       struct extent_buffer *leaf_l;
+                       struct extent_buffer *leaf_r;
+                       struct btrfs_file_extent_item *ei_l;
+                       struct btrfs_file_extent_item *ei_r;
+
+                       leaf_l = sctx->left_path->nodes[0];
+                       leaf_r = sctx->right_path->nodes[0];
+                       ei_l = btrfs_item_ptr(leaf_l,
+                                             sctx->left_path->slots[0],
+                                             struct btrfs_file_extent_item);
+                       ei_r = btrfs_item_ptr(leaf_r,
+                                             sctx->right_path->slots[0],
+                                             struct btrfs_file_extent_item);
+
+                       /*
+                        * We may have found an extent item that has changed
+                        * only its disk_bytenr field and the corresponding
+                        * inode item was not updated. This case happens due to
+                        * very specific timings during relocation when a leaf
+                        * that contains file extent items is COWed while
+                        * relocation is ongoing and its in the stage where it
+                        * updates data pointers. So when this happens we can
+                        * safely ignore it since we know it's the same extent,
+                        * but just at different logical and physical locations
+                        * (when an extent is fully replaced with a new one, we
+                        * know the generation number must have changed too,
+                        * since snapshot creation implies committing the current
+                        * transaction, and the inode item must have been updated
+                        * as well).
+                        * This replacement of the disk_bytenr happens at
+                        * relocation.c:replace_file_extents() through
+                        * relocation.c:btrfs_reloc_cow_block().
+                        */
+                       if (btrfs_file_extent_generation(leaf_l, ei_l) ==
+                           btrfs_file_extent_generation(leaf_r, ei_r) &&
+                           btrfs_file_extent_ram_bytes(leaf_l, ei_l) ==
+                           btrfs_file_extent_ram_bytes(leaf_r, ei_r) &&
+                           btrfs_file_extent_compression(leaf_l, ei_l) ==
+                           btrfs_file_extent_compression(leaf_r, ei_r) &&
+                           btrfs_file_extent_encryption(leaf_l, ei_l) ==
+                           btrfs_file_extent_encryption(leaf_r, ei_r) &&
+                           btrfs_file_extent_other_encoding(leaf_l, ei_l) ==
+                           btrfs_file_extent_other_encoding(leaf_r, ei_r) &&
+                           btrfs_file_extent_type(leaf_l, ei_l) ==
+                           btrfs_file_extent_type(leaf_r, ei_r) &&
+                           btrfs_file_extent_disk_bytenr(leaf_l, ei_l) !=
+                           btrfs_file_extent_disk_bytenr(leaf_r, ei_r) &&
+                           btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) ==
+                           btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) &&
+                           btrfs_file_extent_offset(leaf_l, ei_l) ==
+                           btrfs_file_extent_offset(leaf_r, ei_r) &&
+                           btrfs_file_extent_num_bytes(leaf_l, ei_l) ==
+                           btrfs_file_extent_num_bytes(leaf_r, ei_r))
+                               return 0;
+               }
+
                inconsistent_snapshot_error(sctx, result, "extent");
                return -EIO;
        }
index 528cae1..3d33c4e 100644 (file)
@@ -2713,14 +2713,12 @@ static inline void btrfs_remove_all_log_ctxs(struct btrfs_root *root,
                                             int index, int error)
 {
        struct btrfs_log_ctx *ctx;
+       struct btrfs_log_ctx *safe;
 
-       if (!error) {
-               INIT_LIST_HEAD(&root->log_ctxs[index]);
-               return;
-       }
-
-       list_for_each_entry(ctx, &root->log_ctxs[index], list)
+       list_for_each_entry_safe(ctx, safe, &root->log_ctxs[index], list) {
+               list_del_init(&ctx->list);
                ctx->log_ret = error;
+       }
 
        INIT_LIST_HEAD(&root->log_ctxs[index]);
 }
@@ -2961,13 +2959,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
        mutex_unlock(&root->log_mutex);
 
 out_wake_log_root:
-       /*
-        * We needn't get log_mutex here because we are sure all
-        * the other tasks are blocked.
-        */
+       mutex_lock(&log_root_tree->log_mutex);
        btrfs_remove_all_log_ctxs(log_root_tree, index2, ret);
 
-       mutex_lock(&log_root_tree->log_mutex);
        log_root_tree->log_transid_committed++;
        atomic_set(&log_root_tree->log_commit[index2], 0);
        mutex_unlock(&log_root_tree->log_mutex);
@@ -2978,10 +2972,8 @@ out_wake_log_root:
        if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
                wake_up(&log_root_tree->log_commit_wait[index2]);
 out:
-       /* See above. */
-       btrfs_remove_all_log_ctxs(root, index1, ret);
-
        mutex_lock(&root->log_mutex);
+       btrfs_remove_all_log_ctxs(root, index1, ret);
        root->log_transid_committed++;
        atomic_set(&root->log_commit[index1], 0);
        mutex_unlock(&root->log_mutex);
index 7bf0882..18630e8 100644 (file)
@@ -1272,7 +1272,8 @@ again:
                statret = __ceph_do_getattr(inode, page,
                                            CEPH_STAT_CAP_INLINE_DATA, !!page);
                if (statret < 0) {
-                        __free_page(page);
+                       if (page)
+                               __free_page(page);
                        if (statret == -ENODATA) {
                                BUG_ON(retry_op != READ_INLINE);
                                goto again;
index bca1b49..ef4d046 100644 (file)
@@ -1511,7 +1511,8 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                        ceph_fill_dirfrag(d_inode(parent), rinfo->dir_dir);
        }
 
-       if (ceph_frag_is_leftmost(frag) && req->r_readdir_offset == 2) {
+       if (ceph_frag_is_leftmost(frag) && req->r_readdir_offset == 2 &&
+           !(rinfo->hash_order && req->r_path2)) {
                /* note dir version at start of readdir so we can tell
                 * if any dentries get dropped */
                req->r_dir_release_cnt = atomic64_read(&ci->i_release_count);
index a29ffce..b382e59 100644 (file)
@@ -845,6 +845,8 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
                err = ceph_fs_debugfs_init(fsc);
                if (err < 0)
                        goto fail;
+       } else {
+               root = dget(fsc->sb->s_root);
        }
 
        fsc->mount_state = CEPH_MOUNT_MOUNTED;
index 40b7032..febc28f 100644 (file)
@@ -16,7 +16,7 @@
 static int __remove_xattr(struct ceph_inode_info *ci,
                          struct ceph_inode_xattr *xattr);
 
-const struct xattr_handler ceph_other_xattr_handler;
+static const struct xattr_handler ceph_other_xattr_handler;
 
 /*
  * List of handlers for synthetic system.* attributes. Other
@@ -1086,7 +1086,7 @@ static int ceph_set_xattr_handler(const struct xattr_handler *handler,
        return __ceph_setxattr(inode, name, value, size, flags);
 }
 
-const struct xattr_handler ceph_other_xattr_handler = {
+static const struct xattr_handler ceph_other_xattr_handler = {
        .prefix = "",  /* match any name => handlers called with full name */
        .get = ceph_get_xattr_handler,
        .set = ceph_set_xattr_handler,
index 61057b7..98f87fe 100644 (file)
@@ -151,7 +151,10 @@ static int do_page_crypto(struct inode *inode,
                        struct page *src_page, struct page *dest_page,
                        gfp_t gfp_flags)
 {
-       u8 xts_tweak[FS_XTS_TWEAK_SIZE];
+       struct {
+               __le64 index;
+               u8 padding[FS_XTS_TWEAK_SIZE - sizeof(__le64)];
+       } xts_tweak;
        struct skcipher_request *req = NULL;
        DECLARE_FS_COMPLETION_RESULT(ecr);
        struct scatterlist dst, src;
@@ -171,17 +174,15 @@ static int do_page_crypto(struct inode *inode,
                req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
                page_crypt_complete, &ecr);
 
-       BUILD_BUG_ON(FS_XTS_TWEAK_SIZE < sizeof(index));
-       memcpy(xts_tweak, &index, sizeof(index));
-       memset(&xts_tweak[sizeof(index)], 0,
-                       FS_XTS_TWEAK_SIZE - sizeof(index));
+       BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE);
+       xts_tweak.index = cpu_to_le64(index);
+       memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
 
        sg_init_table(&dst, 1);
        sg_set_page(&dst, dest_page, PAGE_SIZE, 0);
        sg_init_table(&src, 1);
        sg_set_page(&src, src_page, PAGE_SIZE, 0);
-       skcipher_request_set_crypt(req, &src, &dst, PAGE_SIZE,
-                                       xts_tweak);
+       skcipher_request_set_crypt(req, &src, &dst, PAGE_SIZE, &xts_tweak);
        if (rw == FS_DECRYPT)
                res = crypto_skcipher_decrypt(req);
        else
index ed115ac..6865663 100644 (file)
@@ -109,6 +109,8 @@ int fscrypt_process_policy(struct file *filp,
        if (ret)
                return ret;
 
+       inode_lock(inode);
+
        if (!inode_has_encryption_context(inode)) {
                if (!S_ISDIR(inode->i_mode))
                        ret = -EINVAL;
@@ -127,6 +129,8 @@ int fscrypt_process_policy(struct file *filp,
                ret = -EINVAL;
        }
 
+       inode_unlock(inode);
+
        mnt_drop_write_file(filp);
        return ret;
 }
index 6fcfb3f..4e497b9 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -191,6 +191,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 {
        struct page *page;
        int ret;
+       unsigned int gup_flags = FOLL_FORCE;
 
 #ifdef CONFIG_STACK_GROWSUP
        if (write) {
@@ -199,12 +200,16 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                        return NULL;
        }
 #endif
+
+       if (write)
+               gup_flags |= FOLL_WRITE;
+
        /*
         * We are doing an exec().  'current' is the process
         * doing the exec and bprm->mm is the new process's mm.
         */
-       ret = get_user_pages_remote(current, bprm->mm, pos, 1, write,
-                       1, &page, NULL);
+       ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags,
+                       &page, NULL);
        if (ret <= 0)
                return NULL;
 
index 7910165..42f9a0a 100644 (file)
@@ -137,7 +137,7 @@ Espan:
 bad_entry:
        EXOFS_ERR(
                "ERROR [exofs_check_page]: bad entry in directory(0x%lx): %s - "
-               "offset=%lu, inode=0x%llu, rec_len=%d, name_len=%d\n",
+               "offset=%lu, inode=0x%llx, rec_len=%d, name_len=%d\n",
                dir->i_ino, error, (page->index<<PAGE_SHIFT)+offs,
                _LLU(le64_to_cpu(p->inode_no)),
                rec_len, p->name_len);
index d831e24..41b8b44 100644 (file)
@@ -622,7 +622,7 @@ static int ext2_get_blocks(struct inode *inode,
                           u32 *bno, bool *new, bool *boundary,
                           int create)
 {
-       int err = -EIO;
+       int err;
        int offsets[4];
        Indirect chain[4];
        Indirect *partial;
@@ -639,7 +639,7 @@ static int ext2_get_blocks(struct inode *inode,
        depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
 
        if (depth == 0)
-               return (err);
+               return -EIO;
 
        partial = ext2_get_branch(inode, depth, offsets, chain, &err);
        /* Simplest case - block found, no allocation needed */
@@ -761,7 +761,6 @@ static int ext2_get_blocks(struct inode *inode,
        ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
        mutex_unlock(&ei->truncate_mutex);
 got_it:
-       *bno = le32_to_cpu(chain[depth-1].key);
        if (count > blocks_to_boundary)
                *boundary = true;
        err = count;
@@ -772,6 +771,8 @@ cleanup:
                brelse(partial->bh);
                partial--;
        }
+       if (err > 0)
+               *bno = le32_to_cpu(chain[depth-1].key);
        return err;
 }
 
index 02ddec6..fdb1954 100644 (file)
@@ -128,12 +128,12 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
        node = rb_first(&sbi->system_blks);
        while (node) {
                entry = rb_entry(node, struct ext4_system_zone, node);
-               printk("%s%llu-%llu", first ? "" : ", ",
+               printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ",
                       entry->start_blk, entry->start_blk + entry->count - 1);
                first = 0;
                node = rb_next(node);
        }
-       printk("\n");
+       printk(KERN_CONT "\n");
 }
 
 int ext4_setup_system_zone(struct super_block *sb)
index 3ef1df6..1aba469 100644 (file)
 #ifdef CONFIG_EXT4_DEBUG
 extern ushort ext4_mballoc_debug;
 
-#define mb_debug(n, fmt, a...)                                         \
-       do {                                                            \
-               if ((n) <= ext4_mballoc_debug) {                        \
-                       printk(KERN_DEBUG "(%s, %d): %s: ",             \
-                              __FILE__, __LINE__, __func__);           \
-                       printk(fmt, ## a);                              \
-               }                                                       \
-       } while (0)
+#define mb_debug(n, fmt, ...)                                          \
+do {                                                                   \
+       if ((n) <= ext4_mballoc_debug) {                                \
+               printk(KERN_DEBUG "(%s, %d): %s: " fmt,                 \
+                      __FILE__, __LINE__, __func__, ##__VA_ARGS__);    \
+       }                                                               \
+} while (0)
 #else
-#define mb_debug(n, fmt, a...)         no_printk(fmt, ## a)
+#define mb_debug(n, fmt, ...)  no_printk(fmt, ##__VA_ARGS__)
 #endif
 
 #define EXT4_MB_HISTORY_ALLOC          1       /* allocation */
index f92f10d..104f8bf 100644 (file)
@@ -577,12 +577,13 @@ static inline unsigned dx_node_limit(struct inode *dir)
 static void dx_show_index(char * label, struct dx_entry *entries)
 {
        int i, n = dx_get_count (entries);
-       printk(KERN_DEBUG "%s index ", label);
+       printk(KERN_DEBUG "%s index", label);
        for (i = 0; i < n; i++) {
-               printk("%x->%lu ", i ? dx_get_hash(entries + i) :
-                               0, (unsigned long)dx_get_block(entries + i));
+               printk(KERN_CONT " %x->%lu",
+                      i ? dx_get_hash(entries + i) : 0,
+                      (unsigned long)dx_get_block(entries + i));
        }
-       printk("\n");
+       printk(KERN_CONT "\n");
 }
 
 struct stats
@@ -679,7 +680,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                }
                de = ext4_next_entry(de, size);
        }
-       printk("(%i)\n", names);
+       printk(KERN_CONT "(%i)\n", names);
        return (struct stats) { names, space, 1 };
 }
 
@@ -798,7 +799,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
                q = entries + count - 1;
                while (p <= q) {
                        m = p + (q - p) / 2;
-                       dxtrace(printk("."));
+                       dxtrace(printk(KERN_CONT "."));
                        if (dx_get_hash(m) > hash)
                                q = m - 1;
                        else
@@ -810,7 +811,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
                        at = entries;
                        while (n--)
                        {
-                               dxtrace(printk(","));
+                               dxtrace(printk(KERN_CONT ","));
                                if (dx_get_hash(++at) > hash)
                                {
                                        at--;
@@ -821,7 +822,8 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
                }
 
                at = p - 1;
-               dxtrace(printk(" %x->%u\n", at == entries ? 0 : dx_get_hash(at),
+               dxtrace(printk(KERN_CONT " %x->%u\n",
+                              at == entries ? 0 : dx_get_hash(at),
                               dx_get_block(at)));
                frame->entries = entries;
                frame->at = at;
index 6db81fb..20da99d 100644 (file)
@@ -597,14 +597,15 @@ void __ext4_std_error(struct super_block *sb, const char *function,
 void __ext4_abort(struct super_block *sb, const char *function,
                unsigned int line, const char *fmt, ...)
 {
+       struct va_format vaf;
        va_list args;
 
        save_error_info(sb, function, line);
        va_start(args, fmt);
-       printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id,
-              function, line);
-       vprintk(fmt, args);
-       printk("\n");
+       vaf.fmt = fmt;
+       vaf.va = &args;
+       printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: %pV\n",
+              sb->s_id, function, line, &vaf);
        va_end(args);
 
        if ((sb->s_flags & MS_RDONLY) == 0) {
@@ -2715,12 +2716,12 @@ static void print_daily_error_info(unsigned long arg)
                       es->s_first_error_func,
                       le32_to_cpu(es->s_first_error_line));
                if (es->s_first_error_ino)
-                       printk(": inode %u",
+                       printk(KERN_CONT ": inode %u",
                               le32_to_cpu(es->s_first_error_ino));
                if (es->s_first_error_block)
-                       printk(": block %llu", (unsigned long long)
+                       printk(KERN_CONT ": block %llu", (unsigned long long)
                               le64_to_cpu(es->s_first_error_block));
-               printk("\n");
+               printk(KERN_CONT "\n");
        }
        if (es->s_last_error_time) {
                printk(KERN_NOTICE "EXT4-fs (%s): last error at time %u: %.*s:%d",
@@ -2729,12 +2730,12 @@ static void print_daily_error_info(unsigned long arg)
                       es->s_last_error_func,
                       le32_to_cpu(es->s_last_error_line));
                if (es->s_last_error_ino)
-                       printk(": inode %u",
+                       printk(KERN_CONT ": inode %u",
                               le32_to_cpu(es->s_last_error_ino));
                if (es->s_last_error_block)
-                       printk(": block %llu", (unsigned long long)
+                       printk(KERN_CONT ": block %llu", (unsigned long long)
                               le64_to_cpu(es->s_last_error_block));
-               printk("\n");
+               printk(KERN_CONT "\n");
        }
        mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);  /* Once a day */
 }
index 73bcfd4..42145be 100644 (file)
@@ -223,14 +223,18 @@ static struct attribute *ext4_attrs[] = {
 EXT4_ATTR_FEATURE(lazy_itable_init);
 EXT4_ATTR_FEATURE(batched_discard);
 EXT4_ATTR_FEATURE(meta_bg_resize);
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
 EXT4_ATTR_FEATURE(encryption);
+#endif
 EXT4_ATTR_FEATURE(metadata_csum_seed);
 
 static struct attribute *ext4_feat_attrs[] = {
        ATTR_LIST(lazy_itable_init),
        ATTR_LIST(batched_discard),
        ATTR_LIST(meta_bg_resize),
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
        ATTR_LIST(encryption),
+#endif
        ATTR_LIST(metadata_csum_seed),
        NULL,
 };
index c15d633..d77be9e 100644 (file)
 #include "acl.h"
 
 #ifdef EXT4_XATTR_DEBUG
-# define ea_idebug(inode, f...) do { \
-               printk(KERN_DEBUG "inode %s:%lu: ", \
-                       inode->i_sb->s_id, inode->i_ino); \
-               printk(f); \
-               printk("\n"); \
-       } while (0)
-# define ea_bdebug(bh, f...) do { \
-               printk(KERN_DEBUG "block %pg:%lu: ",               \
-                      bh->b_bdev, (unsigned long) bh->b_blocknr); \
-               printk(f); \
-               printk("\n"); \
-       } while (0)
+# define ea_idebug(inode, fmt, ...)                                    \
+       printk(KERN_DEBUG "inode %s:%lu: " fmt "\n",                    \
+              inode->i_sb->s_id, inode->i_ino, ##__VA_ARGS__)
+# define ea_bdebug(bh, fmt, ...)                                       \
+       printk(KERN_DEBUG "block %pg:%lu: " fmt "\n",                   \
+              bh->b_bdev, (unsigned long)bh->b_blocknr, ##__VA_ARGS__)
 #else
 # define ea_idebug(inode, fmt, ...)    no_printk(fmt, ##__VA_ARGS__)
 # define ea_bdebug(bh, fmt, ...)       no_printk(fmt, ##__VA_ARGS__)
@@ -241,7 +235,7 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
        int error = -EFSCORRUPTED;
 
        if (((void *) header >= end) ||
-           (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC)))
+           (header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)))
                goto errout;
        error = ext4_xattr_check_names(entry, end, entry);
 errout:
index 93985c6..6f14ee9 100644 (file)
@@ -852,16 +852,16 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
 
        for (segno = start_segno; segno < end_segno; segno++) {
 
-               if (get_valid_blocks(sbi, segno, 1) == 0 ||
-                                       unlikely(f2fs_cp_error(sbi)))
-                       goto next;
-
                /* find segment summary of victim */
                sum_page = find_get_page(META_MAPPING(sbi),
                                        GET_SUM_BLOCK(sbi, segno));
-               f2fs_bug_on(sbi, !PageUptodate(sum_page));
                f2fs_put_page(sum_page, 0);
 
+               if (get_valid_blocks(sbi, segno, 1) == 0 ||
+                               !PageUptodate(sum_page) ||
+                               unlikely(f2fs_cp_error(sbi)))
+                       goto next;
+
                sum = page_address(sum_page);
                f2fs_bug_on(sbi, type != GET_SUM_TYPE((&sum->footer)));
 
index 013d1d3..a8ee8c3 100644 (file)
@@ -433,8 +433,7 @@ iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length,
        struct page *page = data;
        int ret;
 
-       ret = __block_write_begin_int(page, pos & ~PAGE_MASK, length,
-                       NULL, iomap);
+       ret = __block_write_begin_int(page, pos, length, NULL, iomap);
        if (ret)
                return ret;
 
@@ -561,7 +560,7 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi,
        }
 
        while (len > 0) {
-               ret = iomap_apply(inode, start, len, 0, ops, &ctx,
+               ret = iomap_apply(inode, start, len, IOMAP_REPORT, ops, &ctx,
                                iomap_fiemap_actor);
                /* inode with no (attribute) mapping will give ENOENT */
                if (ret == -ENOENT)
index ad0c745..871c8b3 100644 (file)
@@ -687,6 +687,11 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
        pri_bh = NULL;
 
 root_found:
+       /* We don't support read-write mounts */
+       if (!(s->s_flags & MS_RDONLY)) {
+               error = -EACCES;
+               goto out_freebh;
+       }
 
        if (joliet_level && (pri == NULL || !opt.rock)) {
                /* This is the case of Joliet with the norock mount flag.
@@ -1501,9 +1506,6 @@ struct inode *__isofs_iget(struct super_block *sb,
 static struct dentry *isofs_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
-       /* We don't support read-write mounts */
-       if (!(flags & MS_RDONLY))
-               return ERR_PTR(-EACCES);
        return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
 }
 
index 3d8246a..e165266 100644 (file)
@@ -1149,6 +1149,7 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "file as BJ_Reserved");
                spin_lock(&journal->j_list_lock);
                __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
+               spin_unlock(&journal->j_list_lock);
        } else if (jh->b_transaction == journal->j_committing_transaction) {
                /* first access by this transaction */
                jh->b_modified = 0;
@@ -1156,8 +1157,8 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "set next transaction");
                spin_lock(&journal->j_list_lock);
                jh->b_next_transaction = transaction;
+               spin_unlock(&journal->j_list_lock);
        }
-       spin_unlock(&journal->j_list_lock);
        jbd_unlock_bh_state(bh);
 
        /*
index 2bcb86e..78219d5 100644 (file)
@@ -911,6 +911,7 @@ const struct file_operations kernfs_file_fops = {
        .open           = kernfs_fop_open,
        .release        = kernfs_fop_release,
        .poll           = kernfs_fop_poll,
+       .fsync          = noop_fsync,
 };
 
 /**
index ce93b41..22c5b4a 100644 (file)
@@ -1609,6 +1609,7 @@ int fcntl_getlease(struct file *filp)
 
        ctx = smp_load_acquire(&inode->i_flctx);
        if (ctx && !list_empty_careful(&ctx->flc_lease)) {
+               percpu_down_read_preempt_disable(&file_rwsem);
                spin_lock(&ctx->flc_lock);
                time_out_leases(inode, &dispose);
                list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
@@ -1618,6 +1619,8 @@ int fcntl_getlease(struct file *filp)
                        break;
                }
                spin_unlock(&ctx->flc_lock);
+               percpu_up_read_preempt_enable(&file_rwsem);
+
                locks_dispose_list(&dispose);
        }
        return type;
@@ -2529,11 +2532,14 @@ locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
        if (list_empty(&ctx->flc_lease))
                return;
 
+       percpu_down_read_preempt_disable(&file_rwsem);
        spin_lock(&ctx->flc_lock);
        list_for_each_entry_safe(fl, tmp, &ctx->flc_lease, fl_list)
                if (filp == fl->fl_file)
                        lease_modify(fl, F_UNLCK, &dispose);
        spin_unlock(&ctx->flc_lock);
+       percpu_up_read_preempt_enable(&file_rwsem);
+
        locks_dispose_list(&dispose);
 }
 
index 2178476..2905479 100644 (file)
@@ -344,9 +344,10 @@ static void bl_write_cleanup(struct work_struct *work)
                u64 start = hdr->args.offset & (loff_t)PAGE_MASK;
                u64 end = (hdr->args.offset + hdr->args.count +
                        PAGE_SIZE - 1) & (loff_t)PAGE_MASK;
+               u64 lwb = hdr->args.offset + hdr->args.count;
 
                ext_tree_mark_written(bl, start >> SECTOR_SHIFT,
-                                       (end - start) >> SECTOR_SHIFT, end);
+                                       (end - start) >> SECTOR_SHIFT, lwb);
        }
 
        pnfs_ld_write_done(hdr);
index ad917bd..7897826 100644 (file)
@@ -1545,7 +1545,7 @@ static int update_open_stateid(struct nfs4_state *state,
        struct nfs_client *clp = server->nfs_client;
        struct nfs_inode *nfsi = NFS_I(state->inode);
        struct nfs_delegation *deleg_cur;
-       nfs4_stateid freeme = {0};
+       nfs4_stateid freeme = { };
        int ret = 0;
 
        fmode &= (FMODE_READ|FMODE_WRITE);
index 1e8fe84..5355efb 100644 (file)
@@ -73,7 +73,7 @@ static int orangefs_revalidate_lookup(struct dentry *dentry)
                }
        }
 
-       dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+       orangefs_set_timeout(dentry);
        ret = 1;
 out_release_op:
        op_release(new_op);
@@ -94,8 +94,9 @@ out_drop:
 static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        int ret;
+       unsigned long time = (unsigned long) dentry->d_fsdata;
 
-       if (time_before(jiffies, dentry->d_time))
+       if (time_before(jiffies, time))
                return 1;
 
        if (flags & LOOKUP_RCU)
index 66ea0cc..02cc613 100644 (file)
@@ -621,9 +621,9 @@ static int orangefs_file_release(struct inode *inode, struct file *file)
         * readahead cache (if any); this forces an expensive refresh of
         * data for the next caller of mmap (or 'get_block' accesses)
         */
-       if (file->f_path.dentry->d_inode &&
-           file->f_path.dentry->d_inode->i_mapping &&
-           mapping_nrpages(&file->f_path.dentry->d_inode->i_data)) {
+       if (file_inode(file) &&
+           file_inode(file)->i_mapping &&
+           mapping_nrpages(&file_inode(file)->i_data)) {
                if (orangefs_features & ORANGEFS_FEATURE_READAHEAD) {
                        gossip_debug(GOSSIP_INODE_DEBUG,
                            "calling flush_racache on %pU\n",
@@ -632,7 +632,7 @@ static int orangefs_file_release(struct inode *inode, struct file *file)
                        gossip_debug(GOSSIP_INODE_DEBUG,
                            "flush_racache finished\n");
                }
-               truncate_inode_pages(file->f_path.dentry->d_inode->i_mapping,
+               truncate_inode_pages(file_inode(file)->i_mapping,
                                     0);
        }
        return 0;
@@ -648,7 +648,7 @@ static int orangefs_fsync(struct file *file,
 {
        int ret = -EINVAL;
        struct orangefs_inode_s *orangefs_inode =
-               ORANGEFS_I(file->f_path.dentry->d_inode);
+               ORANGEFS_I(file_inode(file));
        struct orangefs_kernel_op_s *new_op = NULL;
 
        /* required call */
@@ -661,7 +661,7 @@ static int orangefs_fsync(struct file *file,
 
        ret = service_operation(new_op,
                        "orangefs_fsync",
-                       get_interruptible_flag(file->f_path.dentry->d_inode));
+                       get_interruptible_flag(file_inode(file)));
 
        gossip_debug(GOSSIP_FILE_DEBUG,
                     "orangefs_fsync got return value of %d\n",
@@ -669,7 +669,7 @@ static int orangefs_fsync(struct file *file,
 
        op_release(new_op);
 
-       orangefs_flush_inode(file->f_path.dentry->d_inode);
+       orangefs_flush_inode(file_inode(file));
        return ret;
 }
 
index d15d3d2..a290ff6 100644 (file)
@@ -72,7 +72,7 @@ static int orangefs_create(struct inode *dir,
 
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
-       dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+       orangefs_set_timeout(dentry);
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
 
        gossip_debug(GOSSIP_NAME_DEBUG,
@@ -183,7 +183,7 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry,
                goto out;
        }
 
-       dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+       orangefs_set_timeout(dentry);
 
        inode = orangefs_iget(dir->i_sb, &new_op->downcall.resp.lookup.refn);
        if (IS_ERR(inode)) {
@@ -322,7 +322,7 @@ static int orangefs_symlink(struct inode *dir,
 
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
-       dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+       orangefs_set_timeout(dentry);
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
 
        gossip_debug(GOSSIP_NAME_DEBUG,
@@ -386,7 +386,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 
        d_instantiate(dentry, inode);
        unlock_new_inode(inode);
-       dentry->d_time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+       orangefs_set_timeout(dentry);
        ORANGEFS_I(inode)->getattr_time = jiffies - 1;
 
        gossip_debug(GOSSIP_NAME_DEBUG,
index 0a82048..3bf803d 100644 (file)
@@ -580,4 +580,11 @@ static inline void orangefs_i_size_write(struct inode *inode, loff_t i_size)
 #endif
 }
 
+static inline void orangefs_set_timeout(struct dentry *dentry)
+{
+       unsigned long time = jiffies + orangefs_dcache_timeout_msecs*HZ/1000;
+
+       dentry->d_fsdata = (void *) time;
+}
+
 #endif /* __ORANGEFSKERNEL_H */
index 89600fd..81818ad 100644 (file)
@@ -412,10 +412,11 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
        mm = get_task_mm(task);
        if (mm) {
                vsize = task_vsize(mm);
-               if (permitted) {
-                       eip = KSTK_EIP(task);
-                       esp = KSTK_ESP(task);
-               }
+               /*
+                * esp and eip are intentionally zeroed out.  There is no
+                * non-racy way to read them without freezing the task.
+                * Programs that need reliable values can use ptrace(2).
+                */
        }
 
        get_task_comm(tcomm, task);
index c2964d8..ca651ac 100644 (file)
@@ -832,6 +832,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
        unsigned long addr = *ppos;
        ssize_t copied;
        char *page;
+       unsigned int flags;
 
        if (!mm)
                return 0;
@@ -844,6 +845,11 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
        if (!atomic_inc_not_zero(&mm->mm_users))
                goto free;
 
+       /* Maybe we should limit FOLL_FORCE to actual ptrace users? */
+       flags = FOLL_FORCE;
+       if (write)
+               flags |= FOLL_WRITE;
+
        while (count > 0) {
                int this_len = min_t(int, count, PAGE_SIZE);
 
@@ -852,7 +858,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
                        break;
                }
 
-               this_len = access_remote_vm(mm, addr, page, this_len, write);
+               this_len = access_remote_vm(mm, addr, page, this_len, flags);
                if (!this_len) {
                        if (!copied)
                                copied = -EIO;
@@ -964,8 +970,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
                max_len = min_t(size_t, PAGE_SIZE, count);
                this_len = min(max_len, this_len);
 
-               retval = access_remote_vm(mm, (env_start + src),
-                       page, this_len, 0);
+               retval = access_remote_vm(mm, (env_start + src), page, this_len, 0);
 
                if (retval <= 0) {
                        ret = retval;
@@ -1007,6 +1012,9 @@ static ssize_t auxv_read(struct file *file, char __user *buf,
 {
        struct mm_struct *mm = file->private_data;
        unsigned int nwords = 0;
+
+       if (!mm)
+               return 0;
        do {
                nwords += 2;
        } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
index 6909582..35b92d8 100644 (file)
@@ -266,24 +266,15 @@ static int do_maps_open(struct inode *inode, struct file *file,
  * /proc/PID/maps that is the stack of the main task.
  */
 static int is_stack(struct proc_maps_private *priv,
-                   struct vm_area_struct *vma, int is_pid)
+                   struct vm_area_struct *vma)
 {
-       int stack = 0;
-
-       if (is_pid) {
-               stack = vma->vm_start <= vma->vm_mm->start_stack &&
-                       vma->vm_end >= vma->vm_mm->start_stack;
-       } else {
-               struct inode *inode = priv->inode;
-               struct task_struct *task;
-
-               rcu_read_lock();
-               task = pid_task(proc_pid(inode), PIDTYPE_PID);
-               if (task)
-                       stack = vma_is_stack_for_task(vma, task);
-               rcu_read_unlock();
-       }
-       return stack;
+       /*
+        * We make no effort to guess what a given thread considers to be
+        * its "stack".  It's not even well-defined for programs written
+        * languages like Go.
+        */
+       return vma->vm_start <= vma->vm_mm->start_stack &&
+               vma->vm_end >= vma->vm_mm->start_stack;
 }
 
 static void
@@ -354,7 +345,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
                        goto done;
                }
 
-               if (is_stack(priv, vma, is_pid))
+               if (is_stack(priv, vma))
                        name = "[stack]";
        }
 
@@ -1669,7 +1660,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
                seq_file_path(m, file, "\n\t= ");
        } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
                seq_puts(m, " heap");
-       } else if (is_stack(proc_priv, vma, is_pid)) {
+       } else if (is_stack(proc_priv, vma)) {
                seq_puts(m, " stack");
        }
 
index faacb0c..3717562 100644 (file)
@@ -124,25 +124,17 @@ unsigned long task_statm(struct mm_struct *mm,
 }
 
 static int is_stack(struct proc_maps_private *priv,
-                   struct vm_area_struct *vma, int is_pid)
+                   struct vm_area_struct *vma)
 {
        struct mm_struct *mm = vma->vm_mm;
-       int stack = 0;
-
-       if (is_pid) {
-               stack = vma->vm_start <= mm->start_stack &&
-                       vma->vm_end >= mm->start_stack;
-       } else {
-               struct inode *inode = priv->inode;
-               struct task_struct *task;
-
-               rcu_read_lock();
-               task = pid_task(proc_pid(inode), PIDTYPE_PID);
-               if (task)
-                       stack = vma_is_stack_for_task(vma, task);
-               rcu_read_unlock();
-       }
-       return stack;
+
+       /*
+        * We make no effort to guess what a given thread considers to be
+        * its "stack".  It's not even well-defined for programs written
+        * languages like Go.
+        */
+       return vma->vm_start <= mm->start_stack &&
+               vma->vm_end >= mm->start_stack;
 }
 
 /*
@@ -184,7 +176,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
        if (file) {
                seq_pad(m, ' ');
                seq_file_path(m, file, "");
-       } else if (mm && is_stack(priv, vma, is_pid)) {
+       } else if (mm && is_stack(priv, vma)) {
                seq_pad(m, ' ');
                seq_printf(m, "[stack]");
        }
index c8f60df..ca16c5d 100644 (file)
@@ -439,7 +439,7 @@ static unsigned int vfs_dent_type(uint8_t type)
  */
 static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 {
-       int err;
+       int err = 0;
        struct qstr nm;
        union ubifs_key key;
        struct ubifs_dent_node *dent;
@@ -541,14 +541,20 @@ out:
        kfree(file->private_data);
        file->private_data = NULL;
 
-       if (err != -ENOENT) {
+       if (err != -ENOENT)
                ubifs_err(c, "cannot find next direntry, error %d", err);
-               return err;
-       }
+       else
+               /*
+                * -ENOENT is a non-fatal error in this context, the TNC uses
+                * it to indicate that the cursor moved past the current directory
+                * and readdir() has to stop.
+                */
+               err = 0;
+
 
        /* 2 is a special value indicating that there are no more direntries */
        ctx->pos = 2;
-       return 0;
+       return err;
 }
 
 /* Free saved readdir() state when the directory is closed */
@@ -1060,9 +1066,9 @@ static void unlock_4_inodes(struct inode *inode1, struct inode *inode2,
        mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
 }
 
-static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
-                       struct inode *new_dir, struct dentry *new_dentry,
-                       unsigned int flags)
+static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
+                    struct inode *new_dir, struct dentry *new_dentry,
+                    unsigned int flags)
 {
        struct ubifs_info *c = old_dir->i_sb->s_fs_info;
        struct inode *old_inode = d_inode(old_dentry);
@@ -1323,7 +1329,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
        return err;
 }
 
-static int ubifs_rename2(struct inode *old_dir, struct dentry *old_dentry,
+static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry,
                        unsigned int flags)
 {
@@ -1336,7 +1342,7 @@ static int ubifs_rename2(struct inode *old_dir, struct dentry *old_dentry,
        if (flags & RENAME_EXCHANGE)
                return ubifs_xrename(old_dir, old_dentry, new_dir, new_dentry);
 
-       return ubifs_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
+       return do_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
 }
 
 int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
@@ -1387,7 +1393,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
        .mkdir       = ubifs_mkdir,
        .rmdir       = ubifs_rmdir,
        .mknod       = ubifs_mknod,
-       .rename      = ubifs_rename2,
+       .rename      = ubifs_rename,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
        .listxattr   = ubifs_listxattr,
index 6c2f4d4..d9f9615 100644 (file)
@@ -172,6 +172,7 @@ out_cancel:
        host_ui->xattr_cnt -= 1;
        host_ui->xattr_size -= CALC_DENT_SIZE(nm->len);
        host_ui->xattr_size -= CALC_XATTR_BYTES(size);
+       host_ui->xattr_names -= nm->len;
        mutex_unlock(&host_ui->ui_mutex);
 out_free:
        make_bad_inode(inode);
@@ -478,6 +479,7 @@ out_cancel:
        host_ui->xattr_cnt += 1;
        host_ui->xattr_size += CALC_DENT_SIZE(nm->len);
        host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
+       host_ui->xattr_names += nm->len;
        mutex_unlock(&host_ui->ui_mutex);
        ubifs_release_budget(c, &req);
        make_bad_inode(inode);
index c27344c..c6eb219 100644 (file)
@@ -3974,9 +3974,6 @@ xfs_bmap_remap_alloc(
         * allocating, so skip that check by pretending to be freeing.
         */
        error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
-       if (error)
-               goto error0;
-error0:
        xfs_perag_put(args.pag);
        if (error)
                trace_xfs_bmap_remap_alloc_error(ap->ip, error, _RET_IP_);
@@ -3999,6 +3996,39 @@ xfs_bmap_alloc(
        return xfs_bmap_btalloc(ap);
 }
 
+/* Trim extent to fit a logical block range. */
+void
+xfs_trim_extent(
+       struct xfs_bmbt_irec    *irec,
+       xfs_fileoff_t           bno,
+       xfs_filblks_t           len)
+{
+       xfs_fileoff_t           distance;
+       xfs_fileoff_t           end = bno + len;
+
+       if (irec->br_startoff + irec->br_blockcount <= bno ||
+           irec->br_startoff >= end) {
+               irec->br_blockcount = 0;
+               return;
+       }
+
+       if (irec->br_startoff < bno) {
+               distance = bno - irec->br_startoff;
+               if (isnullstartblock(irec->br_startblock))
+                       irec->br_startblock = DELAYSTARTBLOCK;
+               if (irec->br_startblock != DELAYSTARTBLOCK &&
+                   irec->br_startblock != HOLESTARTBLOCK)
+                       irec->br_startblock += distance;
+               irec->br_startoff += distance;
+               irec->br_blockcount -= distance;
+       }
+
+       if (end < irec->br_startoff + irec->br_blockcount) {
+               distance = irec->br_startoff + irec->br_blockcount - end;
+               irec->br_blockcount -= distance;
+       }
+}
+
 /*
  * Trim the returned map to the required bounds
  */
@@ -4829,6 +4859,219 @@ xfs_bmap_split_indlen(
        return stolen;
 }
 
+int
+xfs_bmap_del_extent_delay(
+       struct xfs_inode        *ip,
+       int                     whichfork,
+       xfs_extnum_t            *idx,
+       struct xfs_bmbt_irec    *got,
+       struct xfs_bmbt_irec    *del)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_bmbt_irec    new;
+       int64_t                 da_old, da_new, da_diff = 0;
+       xfs_fileoff_t           del_endoff, got_endoff;
+       xfs_filblks_t           got_indlen, new_indlen, stolen;
+       int                     error = 0, state = 0;
+       bool                    isrt;
+
+       XFS_STATS_INC(mp, xs_del_exlist);
+
+       isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
+       del_endoff = del->br_startoff + del->br_blockcount;
+       got_endoff = got->br_startoff + got->br_blockcount;
+       da_old = startblockval(got->br_startblock);
+       da_new = 0;
+
+       ASSERT(*idx >= 0);
+       ASSERT(*idx < ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
+       ASSERT(del->br_blockcount > 0);
+       ASSERT(got->br_startoff <= del->br_startoff);
+       ASSERT(got_endoff >= del_endoff);
+
+       if (isrt) {
+               int64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount);
+
+               do_div(rtexts, mp->m_sb.sb_rextsize);
+               xfs_mod_frextents(mp, rtexts);
+       }
+
+       /*
+        * Update the inode delalloc counter now and wait to update the
+        * sb counters as we might have to borrow some blocks for the
+        * indirect block accounting.
+        */
+       xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del->br_blockcount), 0,
+                       isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+       ip->i_delayed_blks -= del->br_blockcount;
+
+       if (whichfork == XFS_COW_FORK)
+               state |= BMAP_COWFORK;
+
+       if (got->br_startoff == del->br_startoff)
+               state |= BMAP_LEFT_CONTIG;
+       if (got_endoff == del_endoff)
+               state |= BMAP_RIGHT_CONTIG;
+
+       switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
+       case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+               /*
+                * Matches the whole extent.  Delete the entry.
+                */
+               xfs_iext_remove(ip, *idx, 1, state);
+               --*idx;
+               break;
+       case BMAP_LEFT_CONTIG:
+               /*
+                * Deleting the first part of the extent.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+               got->br_startoff = del_endoff;
+               got->br_blockcount -= del->br_blockcount;
+               da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip,
+                               got->br_blockcount), da_old);
+               got->br_startblock = nullstartblock((int)da_new);
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+               break;
+       case BMAP_RIGHT_CONTIG:
+               /*
+                * Deleting the last part of the extent.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+               got->br_blockcount = got->br_blockcount - del->br_blockcount;
+               da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip,
+                               got->br_blockcount), da_old);
+               got->br_startblock = nullstartblock((int)da_new);
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+               break;
+       case 0:
+               /*
+                * Deleting the middle of the extent.
+                *
+                * Distribute the original indlen reservation across the two new
+                * extents.  Steal blocks from the deleted extent if necessary.
+                * Stealing blocks simply fudges the fdblocks accounting below.
+                * Warn if either of the new indlen reservations is zero as this
+                * can lead to delalloc problems.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+
+               got->br_blockcount = del->br_startoff - got->br_startoff;
+               got_indlen = xfs_bmap_worst_indlen(ip, got->br_blockcount);
+
+               new.br_blockcount = got_endoff - del_endoff;
+               new_indlen = xfs_bmap_worst_indlen(ip, new.br_blockcount);
+
+               WARN_ON_ONCE(!got_indlen || !new_indlen);
+               stolen = xfs_bmap_split_indlen(da_old, &got_indlen, &new_indlen,
+                                                      del->br_blockcount);
+
+               got->br_startblock = nullstartblock((int)got_indlen);
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, 0, _THIS_IP_);
+
+               new.br_startoff = del_endoff;
+               new.br_state = got->br_state;
+               new.br_startblock = nullstartblock((int)new_indlen);
+
+               ++*idx;
+               xfs_iext_insert(ip, *idx, 1, &new, state);
+
+               da_new = got_indlen + new_indlen - stolen;
+               del->br_blockcount -= stolen;
+               break;
+       }
+
+       ASSERT(da_old >= da_new);
+       da_diff = da_old - da_new;
+       if (!isrt)
+               da_diff += del->br_blockcount;
+       if (da_diff)
+               xfs_mod_fdblocks(mp, da_diff, false);
+       return error;
+}
+
+void
+xfs_bmap_del_extent_cow(
+       struct xfs_inode        *ip,
+       xfs_extnum_t            *idx,
+       struct xfs_bmbt_irec    *got,
+       struct xfs_bmbt_irec    *del)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+       struct xfs_bmbt_irec    new;
+       xfs_fileoff_t           del_endoff, got_endoff;
+       int                     state = BMAP_COWFORK;
+
+       XFS_STATS_INC(mp, xs_del_exlist);
+
+       del_endoff = del->br_startoff + del->br_blockcount;
+       got_endoff = got->br_startoff + got->br_blockcount;
+
+       ASSERT(*idx >= 0);
+       ASSERT(*idx < ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
+       ASSERT(del->br_blockcount > 0);
+       ASSERT(got->br_startoff <= del->br_startoff);
+       ASSERT(got_endoff >= del_endoff);
+       ASSERT(!isnullstartblock(got->br_startblock));
+
+       if (got->br_startoff == del->br_startoff)
+               state |= BMAP_LEFT_CONTIG;
+       if (got_endoff == del_endoff)
+               state |= BMAP_RIGHT_CONTIG;
+
+       switch (state & (BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG)) {
+       case BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
+               /*
+                * Matches the whole extent.  Delete the entry.
+                */
+               xfs_iext_remove(ip, *idx, 1, state);
+               --*idx;
+               break;
+       case BMAP_LEFT_CONTIG:
+               /*
+                * Deleting the first part of the extent.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+               got->br_startoff = del_endoff;
+               got->br_blockcount -= del->br_blockcount;
+               got->br_startblock = del->br_startblock + del->br_blockcount;
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+               break;
+       case BMAP_RIGHT_CONTIG:
+               /*
+                * Deleting the last part of the extent.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+               got->br_blockcount -= del->br_blockcount;
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+               break;
+       case 0:
+               /*
+                * Deleting the middle of the extent.
+                */
+               trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
+               got->br_blockcount = del->br_startoff - got->br_startoff;
+               xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+               trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
+
+               new.br_startoff = del_endoff;
+               new.br_blockcount = got_endoff - del_endoff;
+               new.br_state = got->br_state;
+               new.br_startblock = del->br_startblock + del->br_blockcount;
+
+               ++*idx;
+               xfs_iext_insert(ip, *idx, 1, &new, state);
+               break;
+       }
+}
+
 /*
  * Called by xfs_bmapi to update file extent records and the btree
  * after removing space (or undoing a delayed allocation).
@@ -5171,175 +5414,6 @@ done:
        return error;
 }
 
-/* Remove an extent from the CoW fork.  Similar to xfs_bmap_del_extent. */
-int
-xfs_bunmapi_cow(
-       struct xfs_inode                *ip,
-       struct xfs_bmbt_irec            *del)
-{
-       xfs_filblks_t                   da_new;
-       xfs_filblks_t                   da_old;
-       xfs_fsblock_t                   del_endblock = 0;
-       xfs_fileoff_t                   del_endoff;
-       int                             delay;
-       struct xfs_bmbt_rec_host        *ep;
-       int                             error;
-       struct xfs_bmbt_irec            got;
-       xfs_fileoff_t                   got_endoff;
-       struct xfs_ifork                *ifp;
-       struct xfs_mount                *mp;
-       xfs_filblks_t                   nblks;
-       struct xfs_bmbt_irec            new;
-       /* REFERENCED */
-       uint                            qfield;
-       xfs_filblks_t                   temp;
-       xfs_filblks_t                   temp2;
-       int                             state = BMAP_COWFORK;
-       int                             eof;
-       xfs_extnum_t                    eidx;
-
-       mp = ip->i_mount;
-       XFS_STATS_INC(mp, xs_del_exlist);
-
-       ep = xfs_bmap_search_extents(ip, del->br_startoff, XFS_COW_FORK, &eof,
-                       &eidx, &got, &new);
-
-       ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); ifp = ifp;
-       ASSERT((eidx >= 0) && (eidx < ifp->if_bytes /
-               (uint)sizeof(xfs_bmbt_rec_t)));
-       ASSERT(del->br_blockcount > 0);
-       ASSERT(got.br_startoff <= del->br_startoff);
-       del_endoff = del->br_startoff + del->br_blockcount;
-       got_endoff = got.br_startoff + got.br_blockcount;
-       ASSERT(got_endoff >= del_endoff);
-       delay = isnullstartblock(got.br_startblock);
-       ASSERT(isnullstartblock(del->br_startblock) == delay);
-       qfield = 0;
-       error = 0;
-       /*
-        * If deleting a real allocation, must free up the disk space.
-        */
-       if (!delay) {
-               nblks = del->br_blockcount;
-               qfield = XFS_TRANS_DQ_BCOUNT;
-               /*
-                * Set up del_endblock and cur for later.
-                */
-               del_endblock = del->br_startblock + del->br_blockcount;
-               da_old = da_new = 0;
-       } else {
-               da_old = startblockval(got.br_startblock);
-               da_new = 0;
-               nblks = 0;
-       }
-       qfield = qfield;
-       nblks = nblks;
-
-       /*
-        * Set flag value to use in switch statement.
-        * Left-contig is 2, right-contig is 1.
-        */
-       switch (((got.br_startoff == del->br_startoff) << 1) |
-               (got_endoff == del_endoff)) {
-       case 3:
-               /*
-                * Matches the whole extent.  Delete the entry.
-                */
-               xfs_iext_remove(ip, eidx, 1, BMAP_COWFORK);
-               --eidx;
-               break;
-
-       case 2:
-               /*
-                * Deleting the first part of the extent.
-                */
-               trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_);
-               xfs_bmbt_set_startoff(ep, del_endoff);
-               temp = got.br_blockcount - del->br_blockcount;
-               xfs_bmbt_set_blockcount(ep, temp);
-               if (delay) {
-                       temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
-                               da_old);
-                       xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-                       trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_);
-                       da_new = temp;
-                       break;
-               }
-               xfs_bmbt_set_startblock(ep, del_endblock);
-               trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_);
-               break;
-
-       case 1:
-               /*
-                * Deleting the last part of the extent.
-                */
-               temp = got.br_blockcount - del->br_blockcount;
-               trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_);
-               xfs_bmbt_set_blockcount(ep, temp);
-               if (delay) {
-                       temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
-                               da_old);
-                       xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-                       trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_);
-                       da_new = temp;
-                       break;
-               }
-               trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_);
-               break;
-
-       case 0:
-               /*
-                * Deleting the middle of the extent.
-                */
-               temp = del->br_startoff - got.br_startoff;
-               trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_);
-               xfs_bmbt_set_blockcount(ep, temp);
-               new.br_startoff = del_endoff;
-               temp2 = got_endoff - del_endoff;
-               new.br_blockcount = temp2;
-               new.br_state = got.br_state;
-               if (!delay) {
-                       new.br_startblock = del_endblock;
-               } else {
-                       temp = xfs_bmap_worst_indlen(ip, temp);
-                       xfs_bmbt_set_startblock(ep, nullstartblock((int)temp));
-                       temp2 = xfs_bmap_worst_indlen(ip, temp2);
-                       new.br_startblock = nullstartblock((int)temp2);
-                       da_new = temp + temp2;
-                       while (da_new > da_old) {
-                               if (temp) {
-                                       temp--;
-                                       da_new--;
-                                       xfs_bmbt_set_startblock(ep,
-                                               nullstartblock((int)temp));
-                               }
-                               if (da_new == da_old)
-                                       break;
-                               if (temp2) {
-                                       temp2--;
-                                       da_new--;
-                                       new.br_startblock =
-                                               nullstartblock((int)temp2);
-                               }
-                       }
-               }
-               trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_);
-               xfs_iext_insert(ip, eidx + 1, 1, &new, state);
-               ++eidx;
-               break;
-       }
-
-       /*
-        * Account for change in delayed indirect blocks.
-        * Nothing to do for disk quota accounting here.
-        */
-       ASSERT(da_old >= da_new);
-       if (da_old > da_new)
-               xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
-
-       return error;
-}
-
 /*
  * Unmap (remove) blocks from a file.
  * If nexts is nonzero then the number of extents to remove is limited to
index f97db71..7cae6ec 100644 (file)
@@ -190,6 +190,8 @@ void        xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
 #define        XFS_BMAP_TRACE_EXLIST(ip,c,w)
 #endif
 
+void   xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
+               xfs_filblks_t len);
 int    xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
 void   xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
 void   xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
@@ -221,7 +223,11 @@ int        xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_fileoff_t bno, xfs_filblks_t len, int flags,
                xfs_extnum_t nexts, xfs_fsblock_t *firstblock,
                struct xfs_defer_ops *dfops, int *done);
-int    xfs_bunmapi_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *del);
+int    xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork,
+               xfs_extnum_t *idx, struct xfs_bmbt_irec *got,
+               struct xfs_bmbt_irec *del);
+void   xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx,
+               struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del);
 int    xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
                xfs_extnum_t num);
 uint   xfs_default_attroffset(struct xfs_inode *ip);
index 5c8e6f2..0e80993 100644 (file)
@@ -4826,7 +4826,7 @@ xfs_btree_calc_size(
        return rval;
 }
 
-int
+static int
 xfs_btree_count_blocks_helper(
        struct xfs_btree_cur    *cur,
        int                     level,
index 3cc3cf7..ac9a003 100644 (file)
@@ -191,8 +191,7 @@ xfs_dquot_buf_verify_crc(
        if (mp->m_quotainfo)
                ndquots = mp->m_quotainfo->qi_dqperchunk;
        else
-               ndquots = xfs_calc_dquots_per_chunk(
-                                       XFS_BB_TO_FSB(mp, bp->b_length));
+               ndquots = xfs_calc_dquots_per_chunk(bp->b_length);
 
        for (i = 0; i < ndquots; i++, d++) {
                if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
index f6547fc..6b7579e 100644 (file)
@@ -865,7 +865,6 @@ typedef struct xfs_timestamp {
  * padding field for v3 inodes.
  */
 #define        XFS_DINODE_MAGIC                0x494e  /* 'IN' */
-#define XFS_DINODE_GOOD_VERSION(v)     ((v) >= 1 && (v) <= 3)
 typedef struct xfs_dinode {
        __be16          di_magic;       /* inode magic # = XFS_DINODE_MAGIC */
        __be16          di_mode;        /* mode and type of file */
index 8de9a3a..134424f 100644 (file)
@@ -57,6 +57,17 @@ xfs_inobp_check(
 }
 #endif
 
+bool
+xfs_dinode_good_version(
+       struct xfs_mount *mp,
+       __u8            version)
+{
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               return version == 3;
+
+       return version == 1 || version == 2;
+}
+
 /*
  * If we are doing readahead on an inode buffer, we might be in log recovery
  * reading an inode allocation buffer that hasn't yet been replayed, and hence
@@ -91,7 +102,7 @@ xfs_inode_buf_verify(
 
                dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
                di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
-                           XFS_DINODE_GOOD_VERSION(dip->di_version);
+                       xfs_dinode_good_version(mp, dip->di_version);
                if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
                                                XFS_ERRTAG_ITOBP_INOTOBP,
                                                XFS_RANDOM_ITOBP_INOTOBP))) {
index 62d9d46..3cfe12a 100644 (file)
@@ -74,6 +74,8 @@ void  xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
 void   xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
                               struct xfs_dinode *to);
 
+bool   xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);
+
 #if defined(DEBUG)
 void   xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
 #else
index a314fc7..6e4f7f9 100644 (file)
@@ -249,6 +249,7 @@ xfs_file_dio_aio_read(
        struct xfs_inode        *ip = XFS_I(inode);
        loff_t                  isize = i_size_read(inode);
        size_t                  count = iov_iter_count(to);
+       loff_t                  end = iocb->ki_pos + count - 1;
        struct iov_iter         data;
        struct xfs_buftarg      *target;
        ssize_t                 ret = 0;
@@ -272,49 +273,21 @@ xfs_file_dio_aio_read(
 
        file_accessed(iocb->ki_filp);
 
-       /*
-        * Locking is a bit tricky here. If we take an exclusive lock for direct
-        * IO, we effectively serialise all new concurrent read IO to this file
-        * and block it behind IO that is currently in progress because IO in
-        * progress holds the IO lock shared. We only need to hold the lock
-        * exclusive to blow away the page cache, so only take lock exclusively
-        * if the page cache needs invalidation. This allows the normal direct
-        * IO case of no page cache pages to proceeed concurrently without
-        * serialisation.
-        */
        xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
        if (mapping->nrpages) {
-               xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
-               xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
+               ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, end);
+               if (ret)
+                       goto out_unlock;
 
                /*
-                * The generic dio code only flushes the range of the particular
-                * I/O. Because we take an exclusive lock here, this whole
-                * sequence is considerably more expensive for us. This has a
-                * noticeable performance impact for any file with cached pages,
-                * even when outside of the range of the particular I/O.
-                *
-                * Hence, amortize the cost of the lock against a full file
-                * flush and reduce the chances of repeated iolock cycles going
-                * forward.
+                * Invalidate whole pages. This can return an error if we fail
+                * to invalidate a page, but this should never happen on XFS.
+                * Warn if it does fail.
                 */
-               if (mapping->nrpages) {
-                       ret = filemap_write_and_wait(mapping);
-                       if (ret) {
-                               xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL);
-                               return ret;
-                       }
-
-                       /*
-                        * Invalidate whole pages. This can return an error if
-                        * we fail to invalidate a page, but this should never
-                        * happen on XFS. Warn if it does fail.
-                        */
-                       ret = invalidate_inode_pages2(mapping);
-                       WARN_ON_ONCE(ret);
-                       ret = 0;
-               }
-               xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
+               ret = invalidate_inode_pages2_range(mapping,
+                               iocb->ki_pos >> PAGE_SHIFT, end >> PAGE_SHIFT);
+               WARN_ON_ONCE(ret);
+               ret = 0;
        }
 
        data = *to;
@@ -324,8 +297,9 @@ xfs_file_dio_aio_read(
                iocb->ki_pos += ret;
                iov_iter_advance(to, ret);
        }
-       xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
 
+out_unlock:
+       xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
        return ret;
 }
 
@@ -570,61 +544,49 @@ xfs_file_dio_aio_write(
        if ((iocb->ki_pos | count) & target->bt_logical_sectormask)
                return -EINVAL;
 
-       /* "unaligned" here means not aligned to a filesystem block */
-       if ((iocb->ki_pos & mp->m_blockmask) ||
-           ((iocb->ki_pos + count) & mp->m_blockmask))
-               unaligned_io = 1;
-
        /*
-        * We don't need to take an exclusive lock unless there page cache needs
-        * to be invalidated or unaligned IO is being executed. We don't need to
-        * consider the EOF extension case here because
-        * xfs_file_aio_write_checks() will relock the inode as necessary for
-        * EOF zeroing cases and fill out the new inode size as appropriate.
+        * Don't take the exclusive iolock here unless the I/O is unaligned to
+        * the file system block size.  We don't need to consider the EOF
+        * extension case here because xfs_file_aio_write_checks() will relock
+        * the inode as necessary for EOF zeroing cases and fill out the new
+        * inode size as appropriate.
         */
-       if (unaligned_io || mapping->nrpages)
+       if ((iocb->ki_pos & mp->m_blockmask) ||
+           ((iocb->ki_pos + count) & mp->m_blockmask)) {
+               unaligned_io = 1;
                iolock = XFS_IOLOCK_EXCL;
-       else
+       } else {
                iolock = XFS_IOLOCK_SHARED;
-       xfs_rw_ilock(ip, iolock);
-
-       /*
-        * Recheck if there are cached pages that need invalidate after we got
-        * the iolock to protect against other threads adding new pages while
-        * we were waiting for the iolock.
-        */
-       if (mapping->nrpages && iolock == XFS_IOLOCK_SHARED) {
-               xfs_rw_iunlock(ip, iolock);
-               iolock = XFS_IOLOCK_EXCL;
-               xfs_rw_ilock(ip, iolock);
        }
 
+       xfs_rw_ilock(ip, iolock);
+
        ret = xfs_file_aio_write_checks(iocb, from, &iolock);
        if (ret)
                goto out;
        count = iov_iter_count(from);
        end = iocb->ki_pos + count - 1;
 
-       /*
-        * See xfs_file_dio_aio_read() for why we do a full-file flush here.
-        */
        if (mapping->nrpages) {
-               ret = filemap_write_and_wait(VFS_I(ip)->i_mapping);
+               ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, end);
                if (ret)
                        goto out;
+
                /*
                 * Invalidate whole pages. This can return an error if we fail
                 * to invalidate a page, but this should never happen on XFS.
                 * Warn if it does fail.
                 */
-               ret = invalidate_inode_pages2(VFS_I(ip)->i_mapping);
+               ret = invalidate_inode_pages2_range(mapping,
+                               iocb->ki_pos >> PAGE_SHIFT, end >> PAGE_SHIFT);
                WARN_ON_ONCE(ret);
                ret = 0;
        }
 
        /*
         * If we are doing unaligned IO, wait for all other IO to drain,
-        * otherwise demote the lock if we had to flush cached pages
+        * otherwise demote the lock if we had to take the exclusive lock
+        * for other reasons in xfs_file_aio_write_checks.
         */
        if (unaligned_io)
                inode_dio_wait(inode);
@@ -947,134 +909,6 @@ out_unlock:
        return error;
 }
 
-/*
- * Flush all file writes out to disk.
- */
-static int
-xfs_file_wait_for_io(
-       struct inode    *inode,
-       loff_t          offset,
-       size_t          len)
-{
-       loff_t          rounding;
-       loff_t          ioffset;
-       loff_t          iendoffset;
-       loff_t          bs;
-       int             ret;
-
-       bs = inode->i_sb->s_blocksize;
-       inode_dio_wait(inode);
-
-       rounding = max_t(xfs_off_t, bs, PAGE_SIZE);
-       ioffset = round_down(offset, rounding);
-       iendoffset = round_up(offset + len, rounding) - 1;
-       ret = filemap_write_and_wait_range(inode->i_mapping, ioffset,
-                                          iendoffset);
-       return ret;
-}
-
-/* Hook up to the VFS reflink function */
-STATIC int
-xfs_file_share_range(
-       struct file     *file_in,
-       loff_t          pos_in,
-       struct file     *file_out,
-       loff_t          pos_out,
-       u64             len,
-       bool            is_dedupe)
-{
-       struct inode    *inode_in;
-       struct inode    *inode_out;
-       ssize_t         ret;
-       loff_t          bs;
-       loff_t          isize;
-       int             same_inode;
-       loff_t          blen;
-       unsigned int    flags = 0;
-
-       inode_in = file_inode(file_in);
-       inode_out = file_inode(file_out);
-       bs = inode_out->i_sb->s_blocksize;
-
-       /* Don't touch certain kinds of inodes */
-       if (IS_IMMUTABLE(inode_out))
-               return -EPERM;
-       if (IS_SWAPFILE(inode_in) ||
-           IS_SWAPFILE(inode_out))
-               return -ETXTBSY;
-
-       /* Reflink only works within this filesystem. */
-       if (inode_in->i_sb != inode_out->i_sb)
-               return -EXDEV;
-       same_inode = (inode_in->i_ino == inode_out->i_ino);
-
-       /* Don't reflink dirs, pipes, sockets... */
-       if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
-               return -EISDIR;
-       if (S_ISFIFO(inode_in->i_mode) || S_ISFIFO(inode_out->i_mode))
-               return -EINVAL;
-       if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
-               return -EINVAL;
-
-       /* Don't share DAX file data for now. */
-       if (IS_DAX(inode_in) || IS_DAX(inode_out))
-               return -EINVAL;
-
-       /* Are we going all the way to the end? */
-       isize = i_size_read(inode_in);
-       if (isize == 0)
-               return 0;
-       if (len == 0)
-               len = isize - pos_in;
-
-       /* Ensure offsets don't wrap and the input is inside i_size */
-       if (pos_in + len < pos_in || pos_out + len < pos_out ||
-           pos_in + len > isize)
-               return -EINVAL;
-
-       /* Don't allow dedupe past EOF in the dest file */
-       if (is_dedupe) {
-               loff_t  disize;
-
-               disize = i_size_read(inode_out);
-               if (pos_out >= disize || pos_out + len > disize)
-                       return -EINVAL;
-       }
-
-       /* If we're linking to EOF, continue to the block boundary. */
-       if (pos_in + len == isize)
-               blen = ALIGN(isize, bs) - pos_in;
-       else
-               blen = len;
-
-       /* Only reflink if we're aligned to block boundaries */
-       if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) ||
-           !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs))
-               return -EINVAL;
-
-       /* Don't allow overlapped reflink within the same file */
-       if (same_inode && pos_out + blen > pos_in && pos_out < pos_in + blen)
-               return -EINVAL;
-
-       /* Wait for the completion of any pending IOs on srcfile */
-       ret = xfs_file_wait_for_io(inode_in, pos_in, len);
-       if (ret)
-               goto out;
-       ret = xfs_file_wait_for_io(inode_out, pos_out, len);
-       if (ret)
-               goto out;
-
-       if (is_dedupe)
-               flags |= XFS_REFLINK_DEDUPE;
-       ret = xfs_reflink_remap_range(XFS_I(inode_in), pos_in, XFS_I(inode_out),
-                       pos_out, len, flags);
-       if (ret < 0)
-               goto out;
-
-out:
-       return ret;
-}
-
 STATIC ssize_t
 xfs_file_copy_range(
        struct file     *file_in,
@@ -1086,7 +920,7 @@ xfs_file_copy_range(
 {
        int             error;
 
-       error = xfs_file_share_range(file_in, pos_in, file_out, pos_out,
+       error = xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
                                     len, false);
        if (error)
                return error;
@@ -1101,7 +935,7 @@ xfs_file_clone_range(
        loff_t          pos_out,
        u64             len)
 {
-       return xfs_file_share_range(file_in, pos_in, file_out, pos_out,
+       return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
                                     len, false);
 }
 
@@ -1124,7 +958,7 @@ xfs_file_dedupe_range(
        if (len > XFS_MAX_DEDUPE_LEN)
                len = XFS_MAX_DEDUPE_LEN;
 
-       error = xfs_file_share_range(src_file, loff, dst_file, dst_loff,
+       error = xfs_reflink_remap_range(src_file, loff, dst_file, dst_loff,
                                     len, true);
        if (error)
                return error;
index 14796b7..f295049 100644 (file)
@@ -1656,9 +1656,9 @@ void
 xfs_inode_set_cowblocks_tag(
        xfs_inode_t     *ip)
 {
-       trace_xfs_inode_set_eofblocks_tag(ip);
+       trace_xfs_inode_set_cowblocks_tag(ip);
        return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_cowblocks,
-                       trace_xfs_perag_set_eofblocks,
+                       trace_xfs_perag_set_cowblocks,
                        XFS_ICI_COWBLOCKS_TAG);
 }
 
@@ -1666,7 +1666,7 @@ void
 xfs_inode_clear_cowblocks_tag(
        xfs_inode_t     *ip)
 {
-       trace_xfs_inode_clear_eofblocks_tag(ip);
+       trace_xfs_inode_clear_cowblocks_tag(ip);
        return __xfs_inode_clear_eofblocks_tag(ip,
-                       trace_xfs_perag_clear_eofblocks, XFS_ICI_COWBLOCKS_TAG);
+                       trace_xfs_perag_clear_cowblocks, XFS_ICI_COWBLOCKS_TAG);
 }
index d907eb9..436e109 100644 (file)
@@ -566,6 +566,17 @@ xfs_file_iomap_begin_delay(
        xfs_bmap_search_extents(ip, offset_fsb, XFS_DATA_FORK, &eof, &idx,
                        &got, &prev);
        if (!eof && got.br_startoff <= offset_fsb) {
+               if (xfs_is_reflink_inode(ip)) {
+                       bool            shared;
+
+                       end_fsb = min(XFS_B_TO_FSB(mp, offset + count),
+                                       maxbytes_fsb);
+                       xfs_trim_extent(&got, offset_fsb, end_fsb - offset_fsb);
+                       error = xfs_reflink_reserve_cow(ip, &got, &shared);
+                       if (error)
+                               goto out_unlock;
+               }
+
                trace_xfs_iomap_found(ip, offset, count, 0, &got);
                goto done;
        }
@@ -961,19 +972,13 @@ xfs_file_iomap_begin(
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_bmbt_irec    imap;
        xfs_fileoff_t           offset_fsb, end_fsb;
-       bool                    shared, trimmed;
        int                     nimaps = 1, error = 0;
+       bool                    shared = false, trimmed = false;
        unsigned                lockmode;
 
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
-               error = xfs_reflink_reserve_cow_range(ip, offset, length);
-               if (error < 0)
-                       return error;
-       }
-
        if ((flags & IOMAP_WRITE) && !IS_DAX(inode) &&
                   !xfs_get_extsz_hint(ip)) {
                /* Reserve delalloc blocks for regular writeback. */
@@ -981,7 +986,16 @@ xfs_file_iomap_begin(
                                iomap);
        }
 
-       lockmode = xfs_ilock_data_map_shared(ip);
+       /*
+        * COW writes will allocate delalloc space, so we need to make sure
+        * to take the lock exclusively here.
+        */
+       if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
+               lockmode = XFS_ILOCK_EXCL;
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+       } else {
+               lockmode = xfs_ilock_data_map_shared(ip);
+       }
 
        ASSERT(offset <= mp->m_super->s_maxbytes);
        if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes)
@@ -991,16 +1005,24 @@ xfs_file_iomap_begin(
 
        error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
                               &nimaps, 0);
-       if (error) {
-               xfs_iunlock(ip, lockmode);
-               return error;
+       if (error)
+               goto out_unlock;
+
+       if (flags & IOMAP_REPORT) {
+               /* Trim the mapping to the nearest shared extent boundary. */
+               error = xfs_reflink_trim_around_shared(ip, &imap, &shared,
+                               &trimmed);
+               if (error)
+                       goto out_unlock;
        }
 
-       /* Trim the mapping to the nearest shared extent boundary. */
-       error = xfs_reflink_trim_around_shared(ip, &imap, &shared, &trimmed);
-       if (error) {
-               xfs_iunlock(ip, lockmode);
-               return error;
+       if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
+               error = xfs_reflink_reserve_cow(ip, &imap, &shared);
+               if (error)
+                       goto out_unlock;
+
+               end_fsb = imap.br_startoff + imap.br_blockcount;
+               length = XFS_FSB_TO_B(mp, end_fsb) - offset;
        }
 
        if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
@@ -1039,6 +1061,9 @@ xfs_file_iomap_begin(
        if (shared)
                iomap->flags |= IOMAP_F_SHARED;
        return 0;
+out_unlock:
+       xfs_iunlock(ip, lockmode);
+       return error;
 }
 
 static int
index fc78739..b341f10 100644 (file)
@@ -1009,6 +1009,7 @@ xfs_mountfs(
  out_quota:
        xfs_qm_unmount_quotas(mp);
  out_rtunmount:
+       mp->m_super->s_flags &= ~MS_ACTIVE;
        xfs_rtunmount_inodes(mp);
  out_rele_rip:
        IRELE(rip);
index 5965e94..a279b4e 100644 (file)
@@ -182,7 +182,8 @@ xfs_reflink_trim_around_shared(
        if (!xfs_is_reflink_inode(ip) ||
            ISUNWRITTEN(irec) ||
            irec->br_startblock == HOLESTARTBLOCK ||
-           irec->br_startblock == DELAYSTARTBLOCK) {
+           irec->br_startblock == DELAYSTARTBLOCK ||
+           isnullstartblock(irec->br_startblock)) {
                *shared = false;
                return 0;
        }
@@ -227,50 +228,54 @@ xfs_reflink_trim_around_shared(
        }
 }
 
-/* Create a CoW reservation for a range of blocks within a file. */
-static int
-__xfs_reflink_reserve_cow(
+/*
+ * Trim the passed in imap to the next shared/unshared extent boundary, and
+ * if imap->br_startoff points to a shared extent reserve space for it in the
+ * COW fork.  In this case *shared is set to true, else to false.
+ *
+ * Note that imap will always contain the block numbers for the existing blocks
+ * in the data fork, as the upper layers need them for read-modify-write
+ * operations.
+ */
+int
+xfs_reflink_reserve_cow(
        struct xfs_inode        *ip,
-       xfs_fileoff_t           *offset_fsb,
-       xfs_fileoff_t           end_fsb,
-       bool                    *skipped)
+       struct xfs_bmbt_irec    *imap,
+       bool                    *shared)
 {
-       struct xfs_bmbt_irec    got, prev, imap;
-       xfs_fileoff_t           orig_end_fsb;
-       int                     nimaps, eof = 0, error = 0;
-       bool                    shared = false, trimmed = false;
+       struct xfs_bmbt_irec    got, prev;
+       xfs_fileoff_t           end_fsb, orig_end_fsb;
+       int                     eof = 0, error = 0;
+       bool                    trimmed;
        xfs_extnum_t            idx;
        xfs_extlen_t            align;
 
-       /* Already reserved?  Skip the refcount btree access. */
-       xfs_bmap_search_extents(ip, *offset_fsb, XFS_COW_FORK, &eof, &idx,
+       /*
+        * Search the COW fork extent list first.  This serves two purposes:
+        * first this implement the speculative preallocation using cowextisze,
+        * so that we also unshared block adjacent to shared blocks instead
+        * of just the shared blocks themselves.  Second the lookup in the
+        * extent list is generally faster than going out to the shared extent
+        * tree.
+        */
+       xfs_bmap_search_extents(ip, imap->br_startoff, XFS_COW_FORK, &eof, &idx,
                        &got, &prev);
-       if (!eof && got.br_startoff <= *offset_fsb) {
-               end_fsb = orig_end_fsb = got.br_startoff + got.br_blockcount;
-               trace_xfs_reflink_cow_found(ip, &got);
-               goto done;
-       }
+       if (!eof && got.br_startoff <= imap->br_startoff) {
+               trace_xfs_reflink_cow_found(ip, imap);
+               xfs_trim_extent(imap, got.br_startoff, got.br_blockcount);
 
-       /* Read extent from the source file. */
-       nimaps = 1;
-       error = xfs_bmapi_read(ip, *offset_fsb, end_fsb - *offset_fsb,
-                       &imap, &nimaps, 0);
-       if (error)
-               goto out_unlock;
-       ASSERT(nimaps == 1);
+               *shared = true;
+               return 0;
+       }
 
        /* Trim the mapping to the nearest shared extent boundary. */
-       error = xfs_reflink_trim_around_shared(ip, &imap, &shared, &trimmed);
+       error = xfs_reflink_trim_around_shared(ip, imap, shared, &trimmed);
        if (error)
-               goto out_unlock;
-
-       end_fsb = orig_end_fsb = imap.br_startoff + imap.br_blockcount;
+               return error;
 
        /* Not shared?  Just report the (potentially capped) extent. */
-       if (!shared) {
-               *skipped = true;
-               goto done;
-       }
+       if (!*shared)
+               return 0;
 
        /*
         * Fork all the shared blocks from our write offset until the end of
@@ -278,72 +283,38 @@ __xfs_reflink_reserve_cow(
         */
        error = xfs_qm_dqattach_locked(ip, 0);
        if (error)
-               goto out_unlock;
+               return error;
+
+       end_fsb = orig_end_fsb = imap->br_startoff + imap->br_blockcount;
 
        align = xfs_eof_alignment(ip, xfs_get_cowextsz_hint(ip));
        if (align)
                end_fsb = roundup_64(end_fsb, align);
 
 retry:
-       error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, *offset_fsb,
-                       end_fsb - *offset_fsb, &got,
-                       &prev, &idx, eof);
+       error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
+                       end_fsb - imap->br_startoff, &got, &prev, &idx, eof);
        switch (error) {
        case 0:
                break;
        case -ENOSPC:
        case -EDQUOT:
                /* retry without any preallocation */
-               trace_xfs_reflink_cow_enospc(ip, &imap);
+               trace_xfs_reflink_cow_enospc(ip, imap);
                if (end_fsb != orig_end_fsb) {
                        end_fsb = orig_end_fsb;
                        goto retry;
                }
                /*FALLTHRU*/
        default:
-               goto out_unlock;
+               return error;
        }
 
        if (end_fsb != orig_end_fsb)
                xfs_inode_set_cowblocks_tag(ip);
 
        trace_xfs_reflink_cow_alloc(ip, &got);
-done:
-       *offset_fsb = end_fsb;
-out_unlock:
-       return error;
-}
-
-/* Create a CoW reservation for part of a file. */
-int
-xfs_reflink_reserve_cow_range(
-       struct xfs_inode        *ip,
-       xfs_off_t               offset,
-       xfs_off_t               count)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-       xfs_fileoff_t           offset_fsb, end_fsb;
-       bool                    skipped = false;
-       int                     error;
-
-       trace_xfs_reflink_reserve_cow_range(ip, offset, count);
-
-       offset_fsb = XFS_B_TO_FSBT(mp, offset);
-       end_fsb = XFS_B_TO_FSB(mp, offset + count);
-
-       xfs_ilock(ip, XFS_ILOCK_EXCL);
-       while (offset_fsb < end_fsb) {
-               error = __xfs_reflink_reserve_cow(ip, &offset_fsb, end_fsb,
-                               &skipped);
-               if (error) {
-                       trace_xfs_reflink_reserve_cow_range_error(ip, error,
-                               _RET_IP_);
-                       break;
-               }
-       }
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-       return error;
+       return 0;
 }
 
 /* Allocate all CoW reservations covering a range of blocks in a file. */
@@ -358,9 +329,8 @@ __xfs_reflink_allocate_cow(
        struct xfs_defer_ops    dfops;
        struct xfs_trans        *tp;
        xfs_fsblock_t           first_block;
-       xfs_fileoff_t           next_fsb;
        int                     nimaps = 1, error;
-       bool                    skipped = false;
+       bool                    shared;
 
        xfs_defer_init(&dfops, &first_block);
 
@@ -371,33 +341,38 @@ __xfs_reflink_allocate_cow(
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
 
-       next_fsb = *offset_fsb;
-       error = __xfs_reflink_reserve_cow(ip, &next_fsb, end_fsb, &skipped);
+       /* Read extent from the source file. */
+       nimaps = 1;
+       error = xfs_bmapi_read(ip, *offset_fsb, end_fsb - *offset_fsb,
+                       &imap, &nimaps, 0);
+       if (error)
+               goto out_unlock;
+       ASSERT(nimaps == 1);
+
+       error = xfs_reflink_reserve_cow(ip, &imap, &shared);
        if (error)
                goto out_trans_cancel;
 
-       if (skipped) {
-               *offset_fsb = next_fsb;
+       if (!shared) {
+               *offset_fsb = imap.br_startoff + imap.br_blockcount;
                goto out_trans_cancel;
        }
 
        xfs_trans_ijoin(tp, ip, 0);
-       error = xfs_bmapi_write(tp, ip, *offset_fsb, next_fsb - *offset_fsb,
+       error = xfs_bmapi_write(tp, ip, imap.br_startoff, imap.br_blockcount,
                        XFS_BMAPI_COWFORK, &first_block,
                        XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK),
                        &imap, &nimaps, &dfops);
        if (error)
                goto out_trans_cancel;
 
-       /* We might not have been able to map the whole delalloc extent */
-       *offset_fsb = min(*offset_fsb + imap.br_blockcount, next_fsb);
-
        error = xfs_defer_finish(&tp, &dfops, NULL);
        if (error)
                goto out_trans_cancel;
 
        error = xfs_trans_commit(tp);
 
+       *offset_fsb = imap.br_startoff + imap.br_blockcount;
 out_unlock:
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        return error;
@@ -536,58 +511,49 @@ xfs_reflink_cancel_cow_blocks(
        xfs_fileoff_t                   offset_fsb,
        xfs_fileoff_t                   end_fsb)
 {
-       struct xfs_bmbt_irec            irec;
-       xfs_filblks_t                   count_fsb;
+       struct xfs_ifork                *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+       struct xfs_bmbt_irec            got, prev, del;
+       xfs_extnum_t                    idx;
        xfs_fsblock_t                   firstfsb;
        struct xfs_defer_ops            dfops;
-       int                             error = 0;
-       int                             nimaps;
+       int                             error = 0, eof = 0;
 
        if (!xfs_is_reflink_inode(ip))
                return 0;
 
-       /* Go find the old extent in the CoW fork. */
-       while (offset_fsb < end_fsb) {
-               nimaps = 1;
-               count_fsb = (xfs_filblks_t)(end_fsb - offset_fsb);
-               error = xfs_bmapi_read(ip, offset_fsb, count_fsb, &irec,
-                               &nimaps, XFS_BMAPI_COWFORK);
-               if (error)
-                       break;
-               ASSERT(nimaps == 1);
-
-               trace_xfs_reflink_cancel_cow(ip, &irec);
+       xfs_bmap_search_extents(ip, offset_fsb, XFS_COW_FORK, &eof, &idx,
+                       &got, &prev);
+       if (eof)
+               return 0;
 
-               if (irec.br_startblock == DELAYSTARTBLOCK) {
-                       /* Free a delayed allocation. */
-                       xfs_mod_fdblocks(ip->i_mount, irec.br_blockcount,
-                                       false);
-                       ip->i_delayed_blks -= irec.br_blockcount;
+       while (got.br_startoff < end_fsb) {
+               del = got;
+               xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
+               trace_xfs_reflink_cancel_cow(ip, &del);
 
-                       /* Remove the mapping from the CoW fork. */
-                       error = xfs_bunmapi_cow(ip, &irec);
+               if (isnullstartblock(del.br_startblock)) {
+                       error = xfs_bmap_del_extent_delay(ip, XFS_COW_FORK,
+                                       &idx, &got, &del);
                        if (error)
                                break;
-               } else if (irec.br_startblock == HOLESTARTBLOCK) {
-                       /* empty */
                } else {
                        xfs_trans_ijoin(*tpp, ip, 0);
                        xfs_defer_init(&dfops, &firstfsb);
 
                        /* Free the CoW orphan record. */
                        error = xfs_refcount_free_cow_extent(ip->i_mount,
-                                       &dfops, irec.br_startblock,
-                                       irec.br_blockcount);
+                                       &dfops, del.br_startblock,
+                                       del.br_blockcount);
                        if (error)
                                break;
 
                        xfs_bmap_add_free(ip->i_mount, &dfops,
-                                       irec.br_startblock, irec.br_blockcount,
+                                       del.br_startblock, del.br_blockcount,
                                        NULL);
 
                        /* Update quota accounting */
                        xfs_trans_mod_dquot_byino(*tpp, ip, XFS_TRANS_DQ_BCOUNT,
-                                       -(long)irec.br_blockcount);
+                                       -(long)del.br_blockcount);
 
                        /* Roll the transaction */
                        error = xfs_defer_finish(tpp, &dfops, ip);
@@ -597,15 +563,18 @@ xfs_reflink_cancel_cow_blocks(
                        }
 
                        /* Remove the mapping from the CoW fork. */
-                       error = xfs_bunmapi_cow(ip, &irec);
-                       if (error)
-                               break;
+                       xfs_bmap_del_extent_cow(ip, &idx, &got, &del);
                }
 
-               /* Roll on... */
-               offset_fsb = irec.br_startoff + irec.br_blockcount;
+               if (++idx >= ifp->if_bytes / sizeof(struct xfs_bmbt_rec))
+                       break;
+               xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &got);
        }
 
+       /* clear tag if cow fork is emptied */
+       if (!ifp->if_bytes)
+               xfs_inode_clear_cowblocks_tag(ip);
+
        return error;
 }
 
@@ -668,25 +637,26 @@ xfs_reflink_end_cow(
        xfs_off_t                       offset,
        xfs_off_t                       count)
 {
-       struct xfs_bmbt_irec            irec;
-       struct xfs_bmbt_irec            uirec;
+       struct xfs_ifork                *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
+       struct xfs_bmbt_irec            got, prev, del;
        struct xfs_trans                *tp;
        xfs_fileoff_t                   offset_fsb;
        xfs_fileoff_t                   end_fsb;
-       xfs_filblks_t                   count_fsb;
        xfs_fsblock_t                   firstfsb;
        struct xfs_defer_ops            dfops;
-       int                             error;
+       int                             error, eof = 0;
        unsigned int                    resblks;
-       xfs_filblks_t                   ilen;
        xfs_filblks_t                   rlen;
-       int                             nimaps;
+       xfs_extnum_t                    idx;
 
        trace_xfs_reflink_end_cow(ip, offset, count);
 
+       /* No COW extents?  That's easy! */
+       if (ifp->if_bytes == 0)
+               return 0;
+
        offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
        end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
-       count_fsb = (xfs_filblks_t)(end_fsb - offset_fsb);
 
        /* Start a rolling transaction to switch the mappings */
        resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
@@ -698,72 +668,65 @@ xfs_reflink_end_cow(
        xfs_ilock(ip, XFS_ILOCK_EXCL);
        xfs_trans_ijoin(tp, ip, 0);
 
-       /* Go find the old extent in the CoW fork. */
-       while (offset_fsb < end_fsb) {
-               /* Read extent from the source file */
-               nimaps = 1;
-               count_fsb = (xfs_filblks_t)(end_fsb - offset_fsb);
-               error = xfs_bmapi_read(ip, offset_fsb, count_fsb, &irec,
-                               &nimaps, XFS_BMAPI_COWFORK);
-               if (error)
-                       goto out_cancel;
-               ASSERT(nimaps == 1);
+       xfs_bmap_search_extents(ip, end_fsb - 1, XFS_COW_FORK, &eof, &idx,
+                       &got, &prev);
 
-               ASSERT(irec.br_startblock != DELAYSTARTBLOCK);
-               trace_xfs_reflink_cow_remap(ip, &irec);
+       /* If there is a hole at end_fsb - 1 go to the previous extent */
+       if (eof || got.br_startoff > end_fsb) {
+               ASSERT(idx > 0);
+               xfs_bmbt_get_all(xfs_iext_get_ext(ifp, --idx), &got);
+       }
 
-               /*
-                * We can have a hole in the CoW fork if part of a directio
-                * write is CoW but part of it isn't.
-                */
-               rlen = ilen = irec.br_blockcount;
-               if (irec.br_startblock == HOLESTARTBLOCK)
+       /* Walk backwards until we're out of the I/O range... */
+       while (got.br_startoff + got.br_blockcount > offset_fsb) {
+               del = got;
+               xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
+
+               /* Extent delete may have bumped idx forward */
+               if (!del.br_blockcount) {
+                       idx--;
                        goto next_extent;
+               }
+
+               ASSERT(!isnullstartblock(got.br_startblock));
 
                /* Unmap the old blocks in the data fork. */
-               while (rlen) {
-                       xfs_defer_init(&dfops, &firstfsb);
-                       error = __xfs_bunmapi(tp, ip, irec.br_startoff,
-                                       &rlen, 0, 1, &firstfsb, &dfops);
-                       if (error)
-                               goto out_defer;
-
-                       /*
-                        * Trim the extent to whatever got unmapped.
-                        * Remember, bunmapi works backwards.
-                        */
-                       uirec.br_startblock = irec.br_startblock + rlen;
-                       uirec.br_startoff = irec.br_startoff + rlen;
-                       uirec.br_blockcount = irec.br_blockcount - rlen;
-                       irec.br_blockcount = rlen;
-                       trace_xfs_reflink_cow_remap_piece(ip, &uirec);
+               xfs_defer_init(&dfops, &firstfsb);
+               rlen = del.br_blockcount;
+               error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1,
+                               &firstfsb, &dfops);
+               if (error)
+                       goto out_defer;
 
-                       /* Free the CoW orphan record. */
-                       error = xfs_refcount_free_cow_extent(tp->t_mountp,
-                                       &dfops, uirec.br_startblock,
-                                       uirec.br_blockcount);
-                       if (error)
-                               goto out_defer;
+               /* Trim the extent to whatever got unmapped. */
+               if (rlen) {
+                       xfs_trim_extent(&del, del.br_startoff + rlen,
+                               del.br_blockcount - rlen);
+               }
+               trace_xfs_reflink_cow_remap(ip, &del);
 
-                       /* Map the new blocks into the data fork. */
-                       error = xfs_bmap_map_extent(tp->t_mountp, &dfops,
-                                       ip, &uirec);
-                       if (error)
-                               goto out_defer;
+               /* Free the CoW orphan record. */
+               error = xfs_refcount_free_cow_extent(tp->t_mountp, &dfops,
+                               del.br_startblock, del.br_blockcount);
+               if (error)
+                       goto out_defer;
 
-                       /* Remove the mapping from the CoW fork. */
-                       error = xfs_bunmapi_cow(ip, &uirec);
-                       if (error)
-                               goto out_defer;
+               /* Map the new blocks into the data fork. */
+               error = xfs_bmap_map_extent(tp->t_mountp, &dfops, ip, &del);
+               if (error)
+                       goto out_defer;
 
-                       error = xfs_defer_finish(&tp, &dfops, ip);
-                       if (error)
-                               goto out_defer;
-               }
+               /* Remove the mapping from the CoW fork. */
+               xfs_bmap_del_extent_cow(ip, &idx, &got, &del);
+
+               error = xfs_defer_finish(&tp, &dfops, ip);
+               if (error)
+                       goto out_defer;
 
 next_extent:
-               /* Roll on... */
-               offset_fsb = irec.br_startoff + ilen;
+               if (idx < 0)
+                       break;
+               xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &got);
        }
 
        error = xfs_trans_commit(tp);
@@ -774,7 +737,6 @@ next_extent:
 
 out_defer:
        xfs_defer_cancel(&dfops);
-out_cancel:
        xfs_trans_cancel(tp);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 out:
@@ -1312,19 +1274,26 @@ out_error:
  */
 int
 xfs_reflink_remap_range(
-       struct xfs_inode        *src,
-       xfs_off_t               srcoff,
-       struct xfs_inode        *dest,
-       xfs_off_t               destoff,
-       xfs_off_t               len,
-       unsigned int            flags)
+       struct file             *file_in,
+       loff_t                  pos_in,
+       struct file             *file_out,
+       loff_t                  pos_out,
+       u64                     len,
+       bool                    is_dedupe)
 {
+       struct inode            *inode_in = file_inode(file_in);
+       struct xfs_inode        *src = XFS_I(inode_in);
+       struct inode            *inode_out = file_inode(file_out);
+       struct xfs_inode        *dest = XFS_I(inode_out);
        struct xfs_mount        *mp = src->i_mount;
+       loff_t                  bs = inode_out->i_sb->s_blocksize;
+       bool                    same_inode = (inode_in == inode_out);
        xfs_fileoff_t           sfsbno, dfsbno;
        xfs_filblks_t           fsblen;
-       int                     error;
        xfs_extlen_t            cowextsize;
-       bool                    is_same;
+       loff_t                  isize;
+       ssize_t                 ret;
+       loff_t                  blen;
 
        if (!xfs_sb_version_hasreflink(&mp->m_sb))
                return -EOPNOTSUPP;
@@ -1332,17 +1301,8 @@ xfs_reflink_remap_range(
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       /* Don't reflink realtime inodes */
-       if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
-               return -EINVAL;
-
-       if (flags & ~XFS_REFLINK_ALL)
-               return -EINVAL;
-
-       trace_xfs_reflink_remap_range(src, srcoff, len, dest, destoff);
-
        /* Lock both files against IO */
-       if (src->i_ino == dest->i_ino) {
+       if (same_inode) {
                xfs_ilock(src, XFS_IOLOCK_EXCL);
                xfs_ilock(src, XFS_MMAPLOCK_EXCL);
        } else {
@@ -1350,39 +1310,126 @@ xfs_reflink_remap_range(
                xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL);
        }
 
+       /* Don't touch certain kinds of inodes */
+       ret = -EPERM;
+       if (IS_IMMUTABLE(inode_out))
+               goto out_unlock;
+
+       ret = -ETXTBSY;
+       if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
+               goto out_unlock;
+
+
+       /* Don't reflink dirs, pipes, sockets... */
+       ret = -EISDIR;
+       if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
+               goto out_unlock;
+       ret = -EINVAL;
+       if (S_ISFIFO(inode_in->i_mode) || S_ISFIFO(inode_out->i_mode))
+               goto out_unlock;
+       if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
+               goto out_unlock;
+
+       /* Don't reflink realtime inodes */
+       if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
+               goto out_unlock;
+
+       /* Don't share DAX file data for now. */
+       if (IS_DAX(inode_in) || IS_DAX(inode_out))
+               goto out_unlock;
+
+       /* Are we going all the way to the end? */
+       isize = i_size_read(inode_in);
+       if (isize == 0) {
+               ret = 0;
+               goto out_unlock;
+       }
+
+       if (len == 0)
+               len = isize - pos_in;
+
+       /* Ensure offsets don't wrap and the input is inside i_size */
+       if (pos_in + len < pos_in || pos_out + len < pos_out ||
+           pos_in + len > isize)
+               goto out_unlock;
+
+       /* Don't allow dedupe past EOF in the dest file */
+       if (is_dedupe) {
+               loff_t  disize;
+
+               disize = i_size_read(inode_out);
+               if (pos_out >= disize || pos_out + len > disize)
+                       goto out_unlock;
+       }
+
+       /* If we're linking to EOF, continue to the block boundary. */
+       if (pos_in + len == isize)
+               blen = ALIGN(isize, bs) - pos_in;
+       else
+               blen = len;
+
+       /* Only reflink if we're aligned to block boundaries */
+       if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) ||
+           !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs))
+               goto out_unlock;
+
+       /* Don't allow overlapped reflink within the same file */
+       if (same_inode) {
+               if (pos_out + blen > pos_in && pos_out < pos_in + blen)
+                       goto out_unlock;
+       }
+
+       /* Wait for the completion of any pending IOs on both files */
+       inode_dio_wait(inode_in);
+       if (!same_inode)
+               inode_dio_wait(inode_out);
+
+       ret = filemap_write_and_wait_range(inode_in->i_mapping,
+                       pos_in, pos_in + len - 1);
+       if (ret)
+               goto out_unlock;
+
+       ret = filemap_write_and_wait_range(inode_out->i_mapping,
+                       pos_out, pos_out + len - 1);
+       if (ret)
+               goto out_unlock;
+
+       trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
+
        /*
         * Check that the extents are the same.
         */
-       if (flags & XFS_REFLINK_DEDUPE) {
-               is_same = false;
-               error = xfs_compare_extents(VFS_I(src), srcoff, VFS_I(dest),
-                               destoff, len, &is_same);
-               if (error)
-                       goto out_error;
+       if (is_dedupe) {
+               bool            is_same = false;
+
+               ret = xfs_compare_extents(inode_in, pos_in, inode_out, pos_out,
+                               len, &is_same);
+               if (ret)
+                       goto out_unlock;
                if (!is_same) {
-                       error = -EBADE;
-                       goto out_error;
+                       ret = -EBADE;
+                       goto out_unlock;
                }
        }
 
-       error = xfs_reflink_set_inode_flag(src, dest);
-       if (error)
-               goto out_error;
+       ret = xfs_reflink_set_inode_flag(src, dest);
+       if (ret)
+               goto out_unlock;
 
        /*
         * Invalidate the page cache so that we can clear any CoW mappings
         * in the destination file.
         */
-       truncate_inode_pages_range(&VFS_I(dest)->i_data, destoff,
-                                  PAGE_ALIGN(destoff + len) - 1);
+       truncate_inode_pages_range(&inode_out->i_data, pos_out,
+                                  PAGE_ALIGN(pos_out + len) - 1);
 
-       dfsbno = XFS_B_TO_FSBT(mp, destoff);
-       sfsbno = XFS_B_TO_FSBT(mp, srcoff);
+       dfsbno = XFS_B_TO_FSBT(mp, pos_out);
+       sfsbno = XFS_B_TO_FSBT(mp, pos_in);
        fsblen = XFS_B_TO_FSB(mp, len);
-       error = xfs_reflink_remap_blocks(src, sfsbno, dest, dfsbno, fsblen,
-                       destoff + len);
-       if (error)
-               goto out_error;
+       ret = xfs_reflink_remap_blocks(src, sfsbno, dest, dfsbno, fsblen,
+                       pos_out + len);
+       if (ret)
+               goto out_unlock;
 
        /*
         * Carry the cowextsize hint from src to dest if we're sharing the
@@ -1390,26 +1437,24 @@ xfs_reflink_remap_range(
         * has a cowextsize hint, and the destination file does not.
         */
        cowextsize = 0;
-       if (srcoff == 0 && len == i_size_read(VFS_I(src)) &&
+       if (pos_in == 0 && len == i_size_read(inode_in) &&
            (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) &&
-           destoff == 0 && len >= i_size_read(VFS_I(dest)) &&
+           pos_out == 0 && len >= i_size_read(inode_out) &&
            !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE))
                cowextsize = src->i_d.di_cowextsize;
 
-       error = xfs_reflink_update_dest(dest, destoff + len, cowextsize);
-       if (error)
-               goto out_error;
+       ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize);
 
-out_error:
+out_unlock:
        xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
        xfs_iunlock(src, XFS_IOLOCK_EXCL);
        if (src->i_ino != dest->i_ino) {
                xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
                xfs_iunlock(dest, XFS_IOLOCK_EXCL);
        }
-       if (error)
-               trace_xfs_reflink_remap_range_error(dest, error, _RET_IP_);
-       return error;
+       if (ret)
+               trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
+       return ret;
 }
 
 /*
index 5dc3c8a..fad1160 100644 (file)
@@ -26,8 +26,8 @@ extern int xfs_reflink_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno,
 extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
                struct xfs_bmbt_irec *irec, bool *shared, bool *trimmed);
 
-extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip,
-               xfs_off_t offset, xfs_off_t count);
+extern int xfs_reflink_reserve_cow(struct xfs_inode *ip,
+               struct xfs_bmbt_irec *imap, bool *shared);
 extern int xfs_reflink_allocate_cow_range(struct xfs_inode *ip,
                xfs_off_t offset, xfs_off_t count);
 extern bool xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset,
@@ -43,11 +43,8 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset,
 extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
                xfs_off_t count);
 extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
-#define XFS_REFLINK_DEDUPE     1       /* only reflink if contents match */
-#define XFS_REFLINK_ALL                (XFS_REFLINK_DEDUPE)
-extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff,
-               struct xfs_inode *dest, xfs_off_t destoff, xfs_off_t len,
-               unsigned int flags);
+extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
+               struct file *file_out, loff_t pos_out, u64 len, bool is_dedupe);
 extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip,
                struct xfs_trans **tpp);
 extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset,
index 5f8d55d..276d302 100644 (file)
@@ -512,13 +512,13 @@ static struct attribute *xfs_error_attrs[] = {
 };
 
 
-struct kobj_type xfs_error_cfg_ktype = {
+static struct kobj_type xfs_error_cfg_ktype = {
        .release = xfs_sysfs_release,
        .sysfs_ops = &xfs_sysfs_ops,
        .default_attrs = xfs_error_attrs,
 };
 
-struct kobj_type xfs_error_ktype = {
+static struct kobj_type xfs_error_ktype = {
        .release = xfs_sysfs_release,
        .sysfs_ops = &xfs_sysfs_ops,
 };
index ad188d3..0907752 100644 (file)
@@ -3346,7 +3346,7 @@ DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_alloc);
 DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_found);
 DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_enospc);
 
-DEFINE_RW_EVENT(xfs_reflink_reserve_cow_range);
+DEFINE_RW_EVENT(xfs_reflink_reserve_cow);
 DEFINE_RW_EVENT(xfs_reflink_allocate_cow_range);
 
 DEFINE_INODE_IREC_EVENT(xfs_reflink_bounce_dio_write);
@@ -3356,9 +3356,7 @@ DEFINE_INODE_IREC_EVENT(xfs_reflink_trim_irec);
 DEFINE_SIMPLE_IO_EVENT(xfs_reflink_cancel_cow_range);
 DEFINE_SIMPLE_IO_EVENT(xfs_reflink_end_cow);
 DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap);
-DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap_piece);
 
-DEFINE_INODE_ERROR_EVENT(xfs_reflink_reserve_cow_range_error);
 DEFINE_INODE_ERROR_EVENT(xfs_reflink_allocate_cow_range_error);
 DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_cow_range_error);
 DEFINE_INODE_ERROR_EVENT(xfs_reflink_end_cow_error);
index 17a940a..8caa79c 100644 (file)
@@ -21,7 +21,7 @@ extern void pcc_mbox_free_channel(struct mbox_chan *chan);
 static inline struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
                                                         int subspace_id)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 static inline void pcc_mbox_free_channel(struct mbox_chan *chan) { }
 #endif
index 43199a0..63554e9 100644 (file)
@@ -70,7 +70,7 @@ KSYM(__kcrctab_\name):
 #include <generated/autoksyms.h>
 
 #define __EXPORT_SYMBOL(sym, val, sec)                         \
-       __cond_export_sym(sym, val, sec, config_enabled(__KSYM_##sym))
+       __cond_export_sym(sym, val, sec, __is_defined(__KSYM_##sym))
 #define __cond_export_sym(sym, val, sec, conf)                 \
        ___cond_export_sym(sym, val, sec, conf)
 #define ___cond_export_sym(sym, val, sec, enabled)             \
index ddbeda6..689a8b9 100644 (file)
@@ -326,6 +326,7 @@ struct pci_dev;
 int acpi_pci_irq_enable (struct pci_dev *dev);
 void acpi_penalize_isa_irq(int irq, int active);
 bool acpi_isa_irq_available(int irq);
+void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
 extern int ec_read(u8 addr, u8 *val);
index af59638..a428aec 100644 (file)
@@ -785,7 +785,7 @@ extern struct of_device_id __clk_of_table;
  * routines, one at of_clk_init(), and one at platform device probe
  */
 #define CLK_OF_DECLARE_DRIVER(name, compat, fn) \
-       static void name##_of_clk_init_driver(struct device_node *np)   \
+       static void __init name##_of_clk_init_driver(struct device_node *np) \
        {                                                               \
                of_node_clear_flag(np, OF_POPULATED);                   \
                fn(np);                                                 \
index 5fa55fc..32dc0cb 100644 (file)
@@ -677,10 +677,10 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy,
                if (best == table - 1)
                        return pos - table;
 
-               return best - pos;
+               return best - table;
        }
 
-       return best - pos;
+       return best - table;
 }
 
 /* Works only on sorted freq-tables */
index 9b207a8..afe641c 100644 (file)
@@ -81,6 +81,7 @@ enum cpuhp_state {
        CPUHP_AP_ARM_ARCH_TIMER_STARTING,
        CPUHP_AP_ARM_GLOBAL_TIMER_STARTING,
        CPUHP_AP_DUMMY_TIMER_STARTING,
+       CPUHP_AP_JCORE_TIMER_STARTING,
        CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING,
        CPUHP_AP_ARM_TWD_STARTING,
        CPUHP_AP_METAG_TIMER_STARTING,
index 6824556..cd184bd 100644 (file)
@@ -1169,13 +1169,6 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
                                         const char *mod_name);
 void vmbus_driver_unregister(struct hv_driver *hv_driver);
 
-static inline const char *vmbus_dev_name(const struct hv_device *device_obj)
-{
-       const struct kobject *kobj = &device_obj->device.kobj;
-
-       return kobj->name;
-}
-
 void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
 
 int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
index e2c8419..82ef36e 100644 (file)
@@ -141,4 +141,26 @@ enum {
 void *memremap(resource_size_t offset, size_t size, unsigned long flags);
 void memunmap(void *addr);
 
+/*
+ * On x86 PAT systems we have memory tracking that keeps track of
+ * the allowed mappings on memory ranges. This tracking works for
+ * all the in-kernel mapping APIs (ioremap*), but where the user
+ * wishes to map a range from a physical device into user memory
+ * the tracking won't be updated. This API is to be used by
+ * drivers which remap physical device pages into userspace,
+ * and wants to make sure they are mapped WC and not UC.
+ */
+#ifndef arch_io_reserve_memtype_wc
+static inline int arch_io_reserve_memtype_wc(resource_size_t base,
+                                            resource_size_t size)
+{
+       return 0;
+}
+
+static inline void arch_io_free_memtype_wc(resource_size_t base,
+                                          resource_size_t size)
+{
+}
+#endif
+
 #endif /* _LINUX_IO_H */
index e63e288..7892f55 100644 (file)
@@ -19,11 +19,15 @@ struct vm_fault;
 #define IOMAP_UNWRITTEN        0x04    /* blocks allocated @blkno in unwritten state */
 
 /*
- * Flags for iomap mappings:
+ * Flags for all iomap mappings:
  */
-#define IOMAP_F_MERGED 0x01    /* contains multiple blocks/extents */
-#define IOMAP_F_SHARED 0x02    /* block shared with another file */
-#define IOMAP_F_NEW    0x04    /* blocks have been newly allocated */
+#define IOMAP_F_NEW    0x01    /* blocks have been newly allocated */
+
+/*
+ * Flags that only need to be reported for IOMAP_REPORT requests:
+ */
+#define IOMAP_F_MERGED 0x10    /* contains multiple blocks/extents */
+#define IOMAP_F_SHARED 0x20    /* block shared with another file */
 
 /*
  * Magic value for blkno:
@@ -42,8 +46,9 @@ struct iomap {
 /*
  * Flags for iomap_begin / iomap_end.  No flag implies a read.
  */
-#define IOMAP_WRITE            (1 << 0)
-#define IOMAP_ZERO             (1 << 1)
+#define IOMAP_WRITE            (1 << 0) /* writing, must allocate blocks */
+#define IOMAP_ZERO             (1 << 1) /* zeroing operation, may skip holes */
+#define IOMAP_REPORT           (1 << 2) /* report extent status, e.g. FIEMAP */
 
 struct iomap_ops {
        /*
index 7e9a789..ca1ad9e 100644 (file)
@@ -123,12 +123,12 @@ struct inet6_skb_parm {
 };
 
 #if defined(CONFIG_NET_L3_MASTER_DEV)
-static inline bool skb_l3mdev_slave(__u16 flags)
+static inline bool ipv6_l3mdev_skb(__u16 flags)
 {
        return flags & IP6SKB_L3SLAVE;
 }
 #else
-static inline bool skb_l3mdev_slave(__u16 flags)
+static inline bool ipv6_l3mdev_skb(__u16 flags)
 {
        return false;
 }
@@ -139,11 +139,22 @@ static inline bool skb_l3mdev_slave(__u16 flags)
 
 static inline int inet6_iif(const struct sk_buff *skb)
 {
-       bool l3_slave = skb_l3mdev_slave(IP6CB(skb)->flags);
+       bool l3_slave = ipv6_l3mdev_skb(IP6CB(skb)->flags);
 
        return l3_slave ? skb->skb_iif : IP6CB(skb)->iif;
 }
 
+/* can not be used in TCP layer after tcp_v6_fill_cb */
+static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if defined(CONFIG_NET_L3_MASTER_DEV)
+       if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+           ipv6_l3mdev_skb(IP6CB(skb)->flags))
+               return true;
+#endif
+       return false;
+}
+
 struct tcp6_request_sock {
        struct tcp_request_sock   tcp6rsk_tcp;
 };
index 8361c8d..b7e3431 100644 (file)
 #define GITS_BASER_TYPE_SHIFT                  (56)
 #define GITS_BASER_TYPE(r)             (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
 #define GITS_BASER_ENTRY_SIZE_SHIFT            (48)
-#define GITS_BASER_ENTRY_SIZE(r)       ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0xff) + 1)
+#define GITS_BASER_ENTRY_SIZE(r)       ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
 #define GITS_BASER_SHAREABILITY_SHIFT  (10)
 #define GITS_BASER_InnerShareable                                      \
        GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
index d600303..820c0ad 100644 (file)
@@ -44,6 +44,7 @@ static inline void kasan_disable_current(void)
 void kasan_unpoison_shadow(const void *address, size_t size);
 
 void kasan_unpoison_task_stack(struct task_struct *task);
+void kasan_unpoison_stack_above_sp_to(const void *watermark);
 
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
@@ -85,6 +86,7 @@ size_t kasan_metadata_size(struct kmem_cache *cache);
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
 
 static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
+static inline void kasan_unpoison_stack_above_sp_to(const void *watermark) {}
 
 static inline void kasan_enable_current(void) {}
 static inline void kasan_disable_current(void) {}
index 15ec117..8f2e059 100644 (file)
@@ -31,7 +31,6 @@
  * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
  * the last step cherry picks the 2nd arg, we get a zero.
  */
-#define config_enabled(cfg)            ___is_defined(cfg)
 #define __is_defined(x)                        ___is_defined(x)
 #define ___is_defined(val)             ____is_defined(__ARG_PLACEHOLDER_##val)
 #define ____is_defined(arg1_or_junk)   __take_second_arg(arg1_or_junk 1, 0)
  * otherwise. For boolean options, this is equivalent to
  * IS_ENABLED(CONFIG_FOO).
  */
-#define IS_BUILTIN(option) config_enabled(option)
+#define IS_BUILTIN(option) __is_defined(option)
 
 /*
  * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
  * otherwise.
  */
-#define IS_MODULE(option) config_enabled(option##_MODULE)
+#define IS_MODULE(option) __is_defined(option##_MODULE)
 
 /*
  * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
index f6a1642..3be7abd 100644 (file)
@@ -1399,7 +1399,8 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
                    u32 *lkey, u32 *rkey);
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
 int mlx4_SYNC_TPT(struct mlx4_dev *dev);
-int mlx4_test_interrupts(struct mlx4_dev *dev);
+int mlx4_test_interrupt(struct mlx4_dev *dev, int vector);
+int mlx4_test_async(struct mlx4_dev *dev);
 int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
                             const u32 offset[], u32 value[],
                             size_t array_len, u8 port);
index 85c4786..ecc451d 100644 (file)
@@ -418,8 +418,12 @@ struct mlx5_core_health {
        u32                             prev;
        int                             miss_counter;
        bool                            sick;
+       /* wq spinlock to synchronize draining */
+       spinlock_t                      wq_lock;
        struct workqueue_struct        *wq;
+       unsigned long                   flags;
        struct work_struct              work;
+       struct delayed_work             recover_work;
 };
 
 struct mlx5_cq_table {
@@ -625,10 +629,6 @@ struct mlx5_db {
        int                     index;
 };
 
-enum {
-       MLX5_DB_PER_PAGE = PAGE_SIZE / L1_CACHE_BYTES,
-};
-
 enum {
        MLX5_COMP_EQ_SIZE = 1024,
 };
@@ -638,13 +638,6 @@ enum {
        MLX5_PTYS_EN = 1 << 2,
 };
 
-struct mlx5_db_pgdir {
-       struct list_head        list;
-       DECLARE_BITMAP(bitmap, MLX5_DB_PER_PAGE);
-       __be32                 *db_page;
-       dma_addr_t              db_dma;
-};
-
 typedef void (*mlx5_cmd_cbk_t)(int status, void *context);
 
 struct mlx5_cmd_work_ent {
@@ -789,6 +782,7 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev);
 int mlx5_health_init(struct mlx5_core_dev *dev);
 void mlx5_start_health_poll(struct mlx5_core_dev *dev);
 void mlx5_stop_health_poll(struct mlx5_core_dev *dev);
+void mlx5_drain_health_wq(struct mlx5_core_dev *dev);
 int mlx5_buf_alloc_node(struct mlx5_core_dev *dev, int size,
                        struct mlx5_buf *buf, int node);
 int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, struct mlx5_buf *buf);
index e9caec6..a92c8d7 100644 (file)
@@ -1266,29 +1266,25 @@ static inline int fixup_user_fault(struct task_struct *tsk,
 }
 #endif
 
-extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
+extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len,
+               unsigned int gup_flags);
 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-               void *buf, int len, int write);
+               void *buf, int len, unsigned int gup_flags);
 
-long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-                     unsigned long start, unsigned long nr_pages,
-                     unsigned int foll_flags, struct page **pages,
-                     struct vm_area_struct **vmas, int *nonblocking);
 long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
                            unsigned long start, unsigned long nr_pages,
-                           int write, int force, struct page **pages,
+                           unsigned int gup_flags, struct page **pages,
                            struct vm_area_struct **vmas);
 long get_user_pages(unsigned long start, unsigned long nr_pages,
-                           int write, int force, struct page **pages,
+                           unsigned int gup_flags, struct page **pages,
                            struct vm_area_struct **vmas);
 long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
-                   int write, int force, struct page **pages, int *locked);
+                   unsigned int gup_flags, struct page **pages, int *locked);
 long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
                               unsigned long start, unsigned long nr_pages,
-                              int write, int force, struct page **pages,
-                              unsigned int gup_flags);
+                              struct page **pages, unsigned int gup_flags);
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
-                   int write, int force, struct page **pages);
+                   struct page **pages, unsigned int gup_flags);
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                        struct page **pages);
 
@@ -1306,7 +1302,7 @@ struct frame_vector {
 struct frame_vector *frame_vector_create(unsigned int nr_frames);
 void frame_vector_destroy(struct frame_vector *vec);
 int get_vaddr_frames(unsigned long start, unsigned int nr_pfns,
-                    bool write, bool force, struct frame_vector *vec);
+                    unsigned int gup_flags, struct frame_vector *vec);
 void put_vaddr_frames(struct frame_vector *vec);
 int frame_vector_to_pages(struct frame_vector *vec);
 void frame_vector_to_pfns(struct frame_vector *vec);
@@ -1391,7 +1387,7 @@ static inline int stack_guard_page_end(struct vm_area_struct *vma,
                !vma_growsup(vma->vm_next, addr);
 }
 
-int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t);
+int vma_is_stack_for_current(struct vm_area_struct *vma);
 
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
                unsigned long old_addr, struct vm_area_struct *new_vma,
@@ -2232,6 +2228,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
 #define FOLL_TRIED     0x800   /* a retry, previous pass started an IO */
 #define FOLL_MLOCK     0x1000  /* lock present pages */
 #define FOLL_REMOTE    0x2000  /* we are working on non-current tsk/mm */
+#define FOLL_COW       0x4000  /* internal GUP flag */
 
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
                        void *data);
index 7f2ae99..0f088f3 100644 (file)
@@ -440,33 +440,7 @@ struct zone {
        seqlock_t               span_seqlock;
 #endif
 
-       /*
-        * wait_table           -- the array holding the hash table
-        * wait_table_hash_nr_entries   -- the size of the hash table array
-        * wait_table_bits      -- wait_table_size == (1 << wait_table_bits)
-        *
-        * The purpose of all these is to keep track of the people
-        * waiting for a page to become available and make them
-        * runnable again when possible. The trouble is that this
-        * consumes a lot of space, especially when so few things
-        * wait on pages at a given time. So instead of using
-        * per-page waitqueues, we use a waitqueue hash table.
-        *
-        * The bucket discipline is to sleep on the same queue when
-        * colliding and wake all in that wait queue when removing.
-        * When something wakes, it must check to be sure its page is
-        * truly available, a la thundering herd. The cost of a
-        * collision is great, but given the expected load of the
-        * table, they should be so rare as to be outweighed by the
-        * benefits from the saved space.
-        *
-        * __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the
-        * primary users of these fields, and in mm/page_alloc.c
-        * free_area_init_core() performs the initialization of them.
-        */
-       wait_queue_head_t       *wait_table;
-       unsigned long           wait_table_hash_nr_entries;
-       unsigned long           wait_table_bits;
+       int initialized;
 
        /* Write-intensive fields used from the page allocator */
        ZONE_PADDING(_pad1_)
@@ -546,7 +520,7 @@ static inline bool zone_spans_pfn(const struct zone *zone, unsigned long pfn)
 
 static inline bool zone_is_initialized(struct zone *zone)
 {
-       return !!zone->wait_table;
+       return zone->initialized;
 }
 
 static inline bool zone_is_empty(struct zone *zone)
index 136ae6b..91ee364 100644 (file)
@@ -2169,7 +2169,10 @@ struct napi_gro_cb {
        /* Used to determine if flush_id can be ignored */
        u8      is_atomic:1;
 
-       /* 5 bit hole */
+       /* Number of gro_receive callbacks this packet already went through */
+       u8 recursion_counter:4;
+
+       /* 1 bit hole */
 
        /* used to support CHECKSUM_COMPLETE for tunneling protocols */
        __wsum  csum;
@@ -2180,6 +2183,40 @@ struct napi_gro_cb {
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
 
+#define GRO_RECURSION_LIMIT 15
+static inline int gro_recursion_inc_test(struct sk_buff *skb)
+{
+       return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT;
+}
+
+typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *);
+static inline struct sk_buff **call_gro_receive(gro_receive_t cb,
+                                               struct sk_buff **head,
+                                               struct sk_buff *skb)
+{
+       if (unlikely(gro_recursion_inc_test(skb))) {
+               NAPI_GRO_CB(skb)->flush |= 1;
+               return NULL;
+       }
+
+       return cb(head, skb);
+}
+
+typedef struct sk_buff **(*gro_receive_sk_t)(struct sock *, struct sk_buff **,
+                                            struct sk_buff *);
+static inline struct sk_buff **call_gro_receive_sk(gro_receive_sk_t cb,
+                                                  struct sock *sk,
+                                                  struct sk_buff **head,
+                                                  struct sk_buff *skb)
+{
+       if (unlikely(gro_recursion_inc_test(skb))) {
+               NAPI_GRO_CB(skb)->flush |= 1;
+               return NULL;
+       }
+
+       return cb(sk, head, skb);
+}
+
 struct packet_type {
        __be16                  type;   /* This is really htons(ether_type). */
        struct net_device       *dev;   /* NULL is wildcarded here           */
@@ -3877,7 +3914,7 @@ struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
             ldev = netdev_all_lower_get_next(dev, &(iter)))
 
 #define netdev_for_each_all_lower_dev_rcu(dev, ldev, iter) \
-       for (iter = (dev)->all_adj_list.lower.next, \
+       for (iter = &(dev)->all_adj_list.lower, \
             ldev = netdev_all_lower_get_next_rcu(dev, &(iter)); \
             ldev; \
             ldev = netdev_all_lower_get_next_rcu(dev, &(iter)))
index 7676557..fc3c242 100644 (file)
@@ -16,7 +16,6 @@
 #define _LINUX_NVME_H
 
 #include <linux/types.h>
-#include <linux/uuid.h>
 
 /* NQN names in commands fields specified one size */
 #define NVMF_NQN_FIELD_LEN     256
@@ -182,7 +181,7 @@ struct nvme_id_ctrl {
        char                    fr[8];
        __u8                    rab;
        __u8                    ieee[3];
-       __u8                    mic;
+       __u8                    cmic;
        __u8                    mdts;
        __le16                  cntlid;
        __le32                  ver;
@@ -202,7 +201,13 @@ struct nvme_id_ctrl {
        __u8                    apsta;
        __le16                  wctemp;
        __le16                  cctemp;
-       __u8                    rsvd270[50];
+       __le16                  mtfa;
+       __le32                  hmpre;
+       __le32                  hmmin;
+       __u8                    tnvmcap[16];
+       __u8                    unvmcap[16];
+       __le32                  rpmbs;
+       __u8                    rsvd316[4];
        __le16                  kas;
        __u8                    rsvd322[190];
        __u8                    sqes;
@@ -267,7 +272,7 @@ struct nvme_id_ns {
        __le16                  nabo;
        __le16                  nabspf;
        __u16                   rsvd46;
-       __le64                  nvmcap[2];
+       __u8                    nvmcap[16];
        __u8                    rsvd64[40];
        __u8                    nguid[16];
        __u8                    eui64[8];
@@ -276,6 +281,16 @@ struct nvme_id_ns {
        __u8                    vs[3712];
 };
 
+enum {
+       NVME_ID_CNS_NS                  = 0x00,
+       NVME_ID_CNS_CTRL                = 0x01,
+       NVME_ID_CNS_NS_ACTIVE_LIST      = 0x02,
+       NVME_ID_CNS_NS_PRESENT_LIST     = 0x10,
+       NVME_ID_CNS_NS_PRESENT          = 0x11,
+       NVME_ID_CNS_CTRL_NS_LIST        = 0x12,
+       NVME_ID_CNS_CTRL_LIST           = 0x13,
+};
+
 enum {
        NVME_NS_FEAT_THIN       = 1 << 0,
        NVME_NS_FLBAS_LBA_MASK  = 0xf,
@@ -556,8 +571,10 @@ enum nvme_admin_opcode {
        nvme_admin_set_features         = 0x09,
        nvme_admin_get_features         = 0x0a,
        nvme_admin_async_event          = 0x0c,
+       nvme_admin_ns_mgmt              = 0x0d,
        nvme_admin_activate_fw          = 0x10,
        nvme_admin_download_fw          = 0x11,
+       nvme_admin_ns_attach            = 0x15,
        nvme_admin_keep_alive           = 0x18,
        nvme_admin_format_nvm           = 0x80,
        nvme_admin_security_send        = 0x81,
@@ -583,6 +600,7 @@ enum {
        NVME_FEAT_WRITE_ATOMIC  = 0x0a,
        NVME_FEAT_ASYNC_EVENT   = 0x0b,
        NVME_FEAT_AUTO_PST      = 0x0c,
+       NVME_FEAT_HOST_MEM_BUF  = 0x0d,
        NVME_FEAT_KATO          = 0x0f,
        NVME_FEAT_SW_PROGRESS   = 0x80,
        NVME_FEAT_HOST_ID       = 0x81,
@@ -745,7 +763,7 @@ struct nvmf_common_command {
 struct nvmf_disc_rsp_page_entry {
        __u8            trtype;
        __u8            adrfam;
-       __u8            nqntype;
+       __u8            subtype;
        __u8            treq;
        __le16          portid;
        __le16          cntlid;
@@ -794,7 +812,7 @@ struct nvmf_connect_command {
 };
 
 struct nvmf_connect_data {
-       uuid_be         hostid;
+       __u8            hostid[16];
        __le16          cntlid;
        char            resv4[238];
        char            subsysnqn[NVMF_NQN_FIELD_LEN];
@@ -905,12 +923,23 @@ enum {
        NVME_SC_INVALID_VECTOR          = 0x108,
        NVME_SC_INVALID_LOG_PAGE        = 0x109,
        NVME_SC_INVALID_FORMAT          = 0x10a,
-       NVME_SC_FIRMWARE_NEEDS_RESET    = 0x10b,
+       NVME_SC_FW_NEEDS_CONV_RESET     = 0x10b,
        NVME_SC_INVALID_QUEUE           = 0x10c,
        NVME_SC_FEATURE_NOT_SAVEABLE    = 0x10d,
        NVME_SC_FEATURE_NOT_CHANGEABLE  = 0x10e,
        NVME_SC_FEATURE_NOT_PER_NS      = 0x10f,
-       NVME_SC_FW_NEEDS_RESET_SUBSYS   = 0x110,
+       NVME_SC_FW_NEEDS_SUBSYS_RESET   = 0x110,
+       NVME_SC_FW_NEEDS_RESET          = 0x111,
+       NVME_SC_FW_NEEDS_MAX_TIME       = 0x112,
+       NVME_SC_FW_ACIVATE_PROHIBITED   = 0x113,
+       NVME_SC_OVERLAPPING_RANGE       = 0x114,
+       NVME_SC_NS_INSUFFICENT_CAP      = 0x115,
+       NVME_SC_NS_ID_UNAVAILABLE       = 0x116,
+       NVME_SC_NS_ALREADY_ATTACHED     = 0x118,
+       NVME_SC_NS_IS_PRIVATE           = 0x119,
+       NVME_SC_NS_NOT_ATTACHED         = 0x11a,
+       NVME_SC_THIN_PROV_NOT_SUPP      = 0x11b,
+       NVME_SC_CTRL_LIST_INVALID       = 0x11c,
 
        /*
         * I/O Command Set Specific - NVM commands:
@@ -941,6 +970,7 @@ enum {
        NVME_SC_REFTAG_CHECK            = 0x284,
        NVME_SC_COMPARE_FAILED          = 0x285,
        NVME_SC_ACCESS_DENIED           = 0x286,
+       NVME_SC_UNWRITTEN_BLOCK         = 0x287,
 
        NVME_SC_DNR                     = 0x4000,
 };
@@ -960,6 +990,7 @@ struct nvme_completion {
        __le16  status;         /* did the command fail, and if so, why? */
 };
 
-#define NVME_VS(major, minor) (((major) << 16) | ((minor) << 8))
+#define NVME_VS(major, minor, tertiary) \
+       (((major) << 16) | ((minor) << 8) | (tertiary))
 
 #endif /* _LINUX_NVME_H */
index 060d0ed..4741ecd 100644 (file)
@@ -1257,6 +1257,7 @@ extern u64 perf_swevent_set_period(struct perf_event *event);
 extern void perf_event_enable(struct perf_event *event);
 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);
 #else /* !CONFIG_PERF_EVENTS: */
 static inline void *
index f9ae903..8978a60 100644 (file)
@@ -146,6 +146,7 @@ enum qed_led_mode {
 #define DIRECT_REG_RD(reg_addr) readl((void __iomem *)(reg_addr))
 
 #define QED_COALESCE_MAX 0xFF
+#define QED_DEFAULT_RX_USECS 12
 
 /* forward */
 struct qed_dev;
index 99fbe6d..f48d64b 100644 (file)
@@ -68,7 +68,7 @@ void qede_roce_unregister_driver(struct qedr_driver *drv);
 
 bool qede_roce_supported(struct qede_dev *dev);
 
-#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
+#if IS_ENABLED(CONFIG_QED_RDMA)
 int qede_roce_dev_add(struct qede_dev *dev);
 void qede_roce_dev_event_open(struct qede_dev *dev);
 void qede_roce_dev_event_close(struct qede_dev *dev);
index 9adc7b2..f667313 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/list.h>
 #include <linux/rbtree.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/bug.h>
 #include <linux/lockdep.h>
@@ -116,22 +117,22 @@ struct reg_sequence {
 #define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \
 ({ \
        ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
-       int ret; \
+       int pollret; \
        might_sleep_if(sleep_us); \
        for (;;) { \
-               ret = regmap_read((map), (addr), &(val)); \
-               if (ret) \
+               pollret = regmap_read((map), (addr), &(val)); \
+               if (pollret) \
                        break; \
                if (cond) \
                        break; \
                if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
-                       ret = regmap_read((map), (addr), &(val)); \
+                       pollret = regmap_read((map), (addr), &(val)); \
                        break; \
                } \
                if (sleep_us) \
                        usleep_range((sleep_us >> 2) + 1, sleep_us); \
        } \
-       ret ?: ((cond) ? 0 : -ETIMEDOUT); \
+       pollret ?: ((cond) ? 0 : -ETIMEDOUT); \
 })
 
 #ifdef CONFIG_REGMAP
index 601258f..32810f2 100644 (file)
@@ -936,6 +936,7 @@ struct sk_buff_fclones {
 
 /**
  *     skb_fclone_busy - check if fclone is busy
+ *     @sk: socket
  *     @skb: buffer
  *
  * Returns true if skb is a fast clone, and its clone is not freed.
index 0d7abb8..91a740f 100644 (file)
@@ -902,8 +902,5 @@ asmlinkage long sys_pkey_mprotect(unsigned long start, size_t len,
                                  unsigned long prot, int pkey);
 asmlinkage long sys_pkey_alloc(unsigned long flags, unsigned long init_val);
 asmlinkage long sys_pkey_free(int pkey);
-//asmlinkage long sys_pkey_get(int pkey, unsigned long flags);
-//asmlinkage long sys_pkey_set(int pkey, unsigned long access_rights,
-//                          unsigned long flags);
 
 #endif
index 45f004e..2873baf 100644 (file)
 struct timespec;
 struct compat_timespec;
 
-#ifdef CONFIG_THREAD_INFO_IN_TASK
-struct thread_info {
-       unsigned long           flags;          /* low level flags */
-};
-
-#define INIT_THREAD_INFO(tsk)                  \
-{                                              \
-       .flags          = 0,                    \
-}
-#endif
-
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 #define current_thread_info() ((struct thread_info *)current)
 #endif
index f2d0727..8f998af 100644 (file)
@@ -174,6 +174,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex,
                      const struct in6_addr *addr);
 int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
                      const struct in6_addr *addr);
+void __ipv6_sock_mc_close(struct sock *sk);
 void ipv6_sock_mc_close(struct sock *sk);
 bool inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
                    const struct in6_addr *src_addr);
index bd19faa..14b51d7 100644 (file)
@@ -4046,6 +4046,18 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
  * that do not do the 802.11/802.3 conversion on the device.
  */
 
+/**
+ * ieee80211_data_to_8023_exthdr - convert an 802.11 data frame to 802.3
+ * @skb: the 802.11 data frame
+ * @ehdr: pointer to a &struct ethhdr that will get the header, instead
+ *     of it being pushed into the SKB
+ * @addr: the device MAC address
+ * @iftype: the virtual interface type
+ * Return: 0 on success. Non-zero on error.
+ */
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+                                 const u8 *addr, enum nl80211_iftype iftype);
+
 /**
  * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
  * @skb: the 802.11 data frame
@@ -4053,8 +4065,11 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
  * @iftype: the virtual interface type
  * Return: 0 on success. Non-zero on error.
  */
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
-                          enum nl80211_iftype iftype);
+static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+                                        enum nl80211_iftype iftype)
+{
+       return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
+}
 
 /**
  * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
@@ -4072,22 +4087,23 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
 /**
  * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
  *
- * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
- * 802.3 frames. The @list will be empty if the decode fails. The
- * @skb is consumed after the function returns.
+ * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames.
+ * The @list will be empty if the decode fails. The @skb must be fully
+ * header-less before being passed in here; it is freed in this function.
  *
- * @skb: The input IEEE 802.11n A-MSDU frame.
+ * @skb: The input A-MSDU frame without any headers.
  * @list: The output list of 802.3 frames. It must be allocated and
  *     initialized by by the caller.
  * @addr: The device MAC address.
  * @iftype: The device interface type.
  * @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
+ * @check_da: DA to check in the inner ethernet header, or NULL
+ * @check_sa: SA to check in the inner ethernet header, or NULL
  */
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
                              const u8 *addr, enum nl80211_iftype iftype,
                              const unsigned int extra_headroom,
-                             bool has_80211_header);
+                             const u8 *check_da, const u8 *check_sa);
 
 /**
  * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
index 515352c..b0576cb 100644 (file)
@@ -190,8 +190,8 @@ struct inet6_dev {
        __u32                   if_flags;
        int                     dead;
 
+       u32                     desync_factor;
        u8                      rndid[8];
-       struct timer_list       regen_timer;
        struct list_head        tempaddr_list;
 
        struct in6_addr         token;
index bc43c0f..5413883 100644 (file)
@@ -38,7 +38,7 @@ struct sock;
 struct inet_skb_parm {
        int                     iif;
        struct ip_options       opt;            /* Compiled IP options          */
-       unsigned char           flags;
+       u16                     flags;
 
 #define IPSKB_FORWARDED                BIT(0)
 #define IPSKB_XFRM_TUNNEL_SIZE BIT(1)
@@ -48,10 +48,16 @@ struct inet_skb_parm {
 #define IPSKB_DOREDIRECT       BIT(5)
 #define IPSKB_FRAG_PMTU                BIT(6)
 #define IPSKB_FRAG_SEGS                BIT(7)
+#define IPSKB_L3SLAVE          BIT(8)
 
        u16                     frag_max_size;
 };
 
+static inline bool ipv4_l3mdev_skb(u16 flags)
+{
+       return !!(flags & IPSKB_L3SLAVE);
+}
+
 static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
 {
        return ip_hdr(skb)->ihl * 4;
@@ -572,7 +578,7 @@ int ip_options_rcv_srr(struct sk_buff *skb);
  */
 
 void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
-void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int offset);
+void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb, int tlen, int offset);
 int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
                 struct ipcm_cookie *ipc, bool allow_ipv6);
 int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
@@ -594,7 +600,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
 
 static inline void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb)
 {
-       ip_cmsg_recv_offset(msg, skb, 0);
+       ip_cmsg_recv_offset(msg, skb, 0, 0);
 }
 
 bool icmp_global_allow(void);
index fb961a5..a74e2aa 100644 (file)
@@ -230,6 +230,8 @@ struct fib6_table {
        rwlock_t                tb6_lock;
        struct fib6_node        tb6_root;
        struct inet_peer_base   tb6_peers;
+       unsigned int            flags;
+#define RT6_TABLE_HAS_DFLT_ROUTER      BIT(0)
 };
 
 #define RT6_TABLE_UNSPEC       RT_TABLE_UNSPEC
index e0cd318..f83e78d 100644 (file)
@@ -32,6 +32,7 @@ struct route_info {
 #define RT6_LOOKUP_F_SRCPREF_TMP       0x00000008
 #define RT6_LOOKUP_F_SRCPREF_PUBLIC    0x00000010
 #define RT6_LOOKUP_F_SRCPREF_COA       0x00000020
+#define RT6_LOOKUP_F_IGNORE_LINKSTATE  0x00000040
 
 /* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
  * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
index a810dfc..e2dba93 100644 (file)
@@ -811,14 +811,18 @@ enum mac80211_rate_control_flags {
  * in the control information, and it will be filled by the rate
  * control algorithm according to what should be sent. For example,
  * if this array contains, in the format { <idx>, <count> } the
- * information
+ * information::
+ *
  *    { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
+ *
  * then this means that the frame should be transmitted
  * up to twice at rate 3, up to twice at rate 2, and up to four
  * times at rate 1 if it doesn't get acknowledged. Say it gets
  * acknowledged by the peer after the fifth attempt, the status
- * information should then contain
+ * information should then contain::
+ *
  *   { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
+ *
  * since it was transmitted twice at rate 3, twice at rate 2
  * and once at rate 1 after which we received an acknowledgement.
  */
@@ -1168,8 +1172,8 @@ enum mac80211_rx_vht_flags {
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *     HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
  * @vht_nss: number of streams (VHT only)
- * @flag: %RX_FLAG_*
- * @vht_flag: %RX_VHT_FLAG_*
+ * @flag: %RX_FLAG_\*
+ * @vht_flag: %RX_VHT_FLAG_\*
  * @rx_flags: internal RX flags for mac80211
  * @ampdu_reference: A-MPDU reference number, must be a different value for
  *     each A-MPDU but the same for each subframe within one A-MPDU
@@ -1432,7 +1436,7 @@ enum ieee80211_vif_flags {
  * @probe_req_reg: probe requests should be reported to mac80211 for this
  *     interface.
  * @drv_priv: data area for driver use, will always be aligned to
- *     sizeof(void *).
+ *     sizeof(void \*).
  * @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
  */
 struct ieee80211_vif {
@@ -1743,7 +1747,7 @@ struct ieee80211_sta_rates {
  * @wme: indicates whether the STA supports QoS/WME (if local devices does,
  *     otherwise always false)
  * @drv_priv: data area for driver use, will always be aligned to
- *     sizeof(void *), size is determined in hw information.
+ *     sizeof(void \*), size is determined in hw information.
  * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
  *     if wme is supported.
  * @max_sp: max Service Period. Only valid if wme is supported.
@@ -2146,12 +2150,12 @@ enum ieee80211_hw_flags {
  *
  * @radiotap_mcs_details: lists which MCS information can the HW
  *     reports, by default it is set to _MCS, _GI and _BW but doesn't
- *     include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
+ *     include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_\* values, only
  *     adding _BW is supported today.
  *
  * @radiotap_vht_details: lists which VHT MCS information the HW reports,
  *     the default is _GI | _BANDWIDTH.
- *     Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
+ *     Use the %IEEE80211_RADIOTAP_VHT_KNOWN_\* values.
  *
  * @radiotap_timestamp: Information for the radiotap timestamp field; if the
  *     'units_pos' member is set to a non-negative value it must be set to
@@ -2486,6 +2490,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  * in the software stack cares about, we will, in the future, have mac80211
  * tell the driver which information elements are interesting in the sense
  * that we want to see changes in them. This will include
+ *
  *  - a list of information element IDs
  *  - a list of OUIs for the vendor information element
  *
index ebf75db..73c6b00 100644 (file)
@@ -252,6 +252,7 @@ struct sock_common {
   *    @sk_pacing_rate: Pacing rate (if supported by transport/packet scheduler)
   *    @sk_max_pacing_rate: Maximum pacing rate (%SO_MAX_PACING_RATE)
   *    @sk_sndbuf: size of send buffer in bytes
+  *    @sk_padding: unused element for alignment
   *    @sk_no_check_tx: %SO_NO_CHECK setting, set checksum in TX packets
   *    @sk_no_check_rx: allow zero checksum in RX packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
@@ -302,7 +303,8 @@ struct sock_common {
   *    @sk_backlog_rcv: callback to process the backlog
   *    @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
   *    @sk_reuseport_cb: reuseport group container
- */
+  *    @sk_rcu: used during RCU grace period
+  */
 struct sock {
        /*
         * Now struct inet_timewait_sock also uses sock_common, so please just
index f83b7f2..5b82d4d 100644 (file)
@@ -794,12 +794,23 @@ struct tcp_skb_cb {
  */
 static inline int tcp_v6_iif(const struct sk_buff *skb)
 {
-       bool l3_slave = skb_l3mdev_slave(TCP_SKB_CB(skb)->header.h6.flags);
+       bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);
 
        return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
 }
 #endif
 
+/* TCP_SKB_CB reference means this can not be used from early demux */
+static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+       if (!net->ipv4.sysctl_tcp_l3mdev_accept &&
+           ipv4_l3mdev_skb(TCP_SKB_CB(skb)->header.h4.flags))
+               return true;
+#endif
+       return false;
+}
+
 /* Due to TSO, an SKB can be composed of multiple actual
  * packets.  To keep these tracked properly, we use this.
  */
index ea53a87..4948790 100644 (file)
@@ -258,6 +258,7 @@ void udp_flush_pending_frames(struct sock *sk);
 void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
 int udp_rcv(struct sk_buff *skb);
 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+int __udp_disconnect(struct sock *sk, int flags);
 int udp_disconnect(struct sock *sk, int flags);
 unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
 struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
index 0255613..308adc4 100644 (file)
@@ -225,9 +225,9 @@ struct vxlan_config {
 struct vxlan_dev {
        struct hlist_node hlist;        /* vni hash table */
        struct list_head  next;         /* vxlan's per namespace list */
-       struct vxlan_sock *vn4_sock;    /* listening socket for IPv4 */
+       struct vxlan_sock __rcu *vn4_sock;      /* listening socket for IPv4 */
 #if IS_ENABLED(CONFIG_IPV6)
-       struct vxlan_sock *vn6_sock;    /* listening socket for IPv6 */
+       struct vxlan_sock __rcu *vn6_sock;      /* listening socket for IPv6 */
 #endif
        struct net_device *dev;
        struct net        *net;         /* netns for packet i/o */
index fb8e3b6..c211900 100644 (file)
@@ -177,6 +177,7 @@ enum tcm_sense_reason_table {
        TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED    = R(0x15),
        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),
 #undef R
 };
 
index dbfee7e..9b1462e 100644 (file)
@@ -730,10 +730,6 @@ __SYSCALL(__NR_pkey_mprotect, sys_pkey_mprotect)
 __SYSCALL(__NR_pkey_alloc,    sys_pkey_alloc)
 #define __NR_pkey_free 290
 __SYSCALL(__NR_pkey_free,     sys_pkey_free)
-#define __NR_pkey_get 291
-//__SYSCALL(__NR_pkey_get,      sys_pkey_get)
-#define __NR_pkey_set 292
-//__SYSCALL(__NR_pkey_set,      sys_pkey_set)
 
 #undef __NR_syscalls
 #define __NR_syscalls 291
index 6965d09..cd2be1c 100644 (file)
@@ -75,6 +75,7 @@ header-y += bpf_perf_event.h
 header-y += bpf.h
 header-y += bpqether.h
 header-y += bsg.h
+header-y += bt-bmc.h
 header-y += btrfs.h
 header-y += can.h
 header-y += capability.h
diff --git a/include/uapi/linux/bt-bmc.h b/include/uapi/linux/bt-bmc.h
new file mode 100644 (file)
index 0000000..d9ec766
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015-2016, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _UAPI_LINUX_BT_BMC_H
+#define _UAPI_LINUX_BT_BMC_H
+
+#include <linux/ioctl.h>
+
+#define __BT_BMC_IOCTL_MAGIC   0xb1
+#define BT_BMC_IOCTL_SMS_ATN   _IO(__BT_BMC_IOCTL_MAGIC, 0x00)
+
+#endif /* _UAPI_LINUX_BT_BMC_H */
index 099a420..8e54723 100644 (file)
@@ -119,8 +119,7 @@ struct ethtool_cmd {
 static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
                                         __u32 speed)
 {
-
-       ep->speed = (__u16)speed;
+       ep->speed = (__u16)(speed & 0xFFFF);
        ep->speed_hi = (__u16)(speed >> 16);
 }
 
index 262f037..5a78be5 100644 (file)
@@ -350,7 +350,7 @@ struct rtnexthop {
 #define RTNH_F_OFFLOAD         8       /* offloaded route */
 #define RTNH_F_LINKDOWN                16      /* carrier-down on nexthop */
 
-#define RTNH_COMPARE_MASK      (RTNH_F_DEAD | RTNH_F_LINKDOWN)
+#define RTNH_COMPARE_MASK      (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD)
 
 /* Macros to handle hexthops */
 
index a521999..bf74eaa 100644 (file)
@@ -53,7 +53,7 @@ static struct msg_msg *alloc_msg(size_t len)
        size_t alen;
 
        alen = min(len, DATALEN_MSG);
-       msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+       msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
        if (msg == NULL)
                return NULL;
 
@@ -65,7 +65,7 @@ static struct msg_msg *alloc_msg(size_t len)
        while (len > 0) {
                struct msg_msgseg *seg;
                alen = min(len, DATALEN_SEG);
-               seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
+               seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
                if (seg == NULL)
                        goto out_err;
                *pseg = seg;
index 5df20d6..29de1a9 100644 (file)
@@ -228,7 +228,7 @@ static struct {
        .wq = __WAIT_QUEUE_HEAD_INITIALIZER(cpu_hotplug.wq),
        .lock = __MUTEX_INITIALIZER(cpu_hotplug.lock),
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
-       .dep_map = {.name = "cpu_hotplug.lock" },
+       .dep_map = STATIC_LOCKDEP_MAP_INIT("cpu_hotplug.dep_map", &cpu_hotplug.dep_map),
 #endif
 };
 
index c6e47e9..0e29213 100644 (file)
@@ -1960,6 +1960,12 @@ void perf_event_disable(struct perf_event *event)
 }
 EXPORT_SYMBOL_GPL(perf_event_disable);
 
+void perf_event_disable_inatomic(struct perf_event *event)
+{
+       event->pending_disable = 1;
+       irq_work_queue(&event->pending);
+}
+
 static void perf_set_shadow_time(struct perf_event *event,
                                 struct perf_event_context *ctx,
                                 u64 tstamp)
@@ -7075,8 +7081,8 @@ static int __perf_event_overflow(struct perf_event *event,
        if (events && atomic_dec_and_test(&event->event_limit)) {
                ret = 1;
                event->pending_kill = POLL_HUP;
-               event->pending_disable = 1;
-               irq_work_queue(&event->pending);
+
+               perf_event_disable_inatomic(event);
        }
 
        READ_ONCE(event->overflow_handler)(event, data, regs);
@@ -8855,7 +8861,10 @@ EXPORT_SYMBOL_GPL(perf_pmu_register);
 
 void perf_pmu_unregister(struct pmu *pmu)
 {
+       int remove_device;
+
        mutex_lock(&pmus_lock);
+       remove_device = pmu_bus_running;
        list_del_rcu(&pmu->entry);
        mutex_unlock(&pmus_lock);
 
@@ -8869,10 +8878,12 @@ void perf_pmu_unregister(struct pmu *pmu)
        free_percpu(pmu->pmu_disable_count);
        if (pmu->type >= PERF_TYPE_MAX)
                idr_remove(&pmu_idr, pmu->type);
-       if (pmu->nr_addr_filters)
-               device_remove_file(pmu->dev, &dev_attr_nr_addr_filters);
-       device_del(pmu->dev);
-       put_device(pmu->dev);
+       if (remove_device) {
+               if (pmu->nr_addr_filters)
+                       device_remove_file(pmu->dev, &dev_attr_nr_addr_filters);
+               device_del(pmu->dev);
+               put_device(pmu->dev);
+       }
        free_pmu_context(pmu);
 }
 EXPORT_SYMBOL_GPL(perf_pmu_unregister);
index d4129bb..f9ec9ad 100644 (file)
@@ -300,7 +300,8 @@ int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
 
 retry:
        /* Read the page with vaddr into memory */
-       ret = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
+       ret = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &old_page,
+                       &vma);
        if (ret <= 0)
                return ret;
 
@@ -1710,7 +1711,8 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
         * but we treat this as a 'remote' access since it is
         * essentially a kernel access to the memory.
         */
-       result = get_user_pages_remote(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+       result = get_user_pages_remote(NULL, mm, vaddr, 1, FOLL_FORCE, &page,
+                       NULL);
        if (result < 0)
                return result;
 
index 0c5f1a5..9c4d304 100644 (file)
@@ -721,6 +721,7 @@ int irq_set_parent(int irq, int parent_irq)
        irq_put_desc_unlock(desc, flags);
        return 0;
 }
+EXPORT_SYMBOL_GPL(irq_set_parent);
 #endif
 
 /*
index 8d44b3f..30e6d05 100644 (file)
@@ -53,8 +53,15 @@ void notrace __sanitizer_cov_trace_pc(void)
        /*
         * We are interested in code coverage as a function of a syscall inputs,
         * so we ignore code executed in interrupts.
+        * The checks for whether we are in an interrupt are open-coded, because
+        * 1. We can't use in_interrupt() here, since it also returns true
+        *    when we are inside local_bh_disable() section.
+        * 2. We don't want to use (in_irq() | in_serving_softirq() | in_nmi()),
+        *    since that leads to slower generated code (three separate tests,
+        *    one for each of the flags).
         */
-       if (!t || in_interrupt())
+       if (!t || (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_OFFSET
+                                                       | NMI_MASK)))
                return;
        mode = READ_ONCE(t->kcov_mode);
        if (mode == KCOV_MODE_TRACE) {
index 1e7f5da..6ccb08f 100644 (file)
@@ -498,9 +498,9 @@ static int enter_state(suspend_state_t state)
 
 #ifndef CONFIG_SUSPEND_SKIP_SYNC
        trace_suspend_resume(TPS("sync_filesystems"), 0, true);
-       printk(KERN_INFO "PM: Syncing filesystems ... ");
+       pr_info("PM: Syncing filesystems ... ");
        sys_sync();
-       printk("done.\n");
+       pr_cont("done.\n");
        trace_suspend_resume(TPS("sync_filesystems"), 0, false);
 #endif
 
index d5e3973..de08fc9 100644 (file)
@@ -1769,6 +1769,10 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c
                cont_flush();
        }
 
+       /* Skip empty continuation lines that couldn't be added - they just flush */
+       if (!text_len && (lflags & LOG_CONT))
+               return 0;
+
        /* If it doesn't end in a newline, try to buffer the current line */
        if (!(lflags & LOG_NEWLINE)) {
                if (cont_add(facility, level, lflags, text, text_len))
index 2a99027..e6474f7 100644 (file)
@@ -537,7 +537,7 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst
                int this_len, retval;
 
                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
-               retval = access_process_vm(tsk, src, buf, this_len, 0);
+               retval = access_process_vm(tsk, src, buf, this_len, FOLL_FORCE);
                if (!retval) {
                        if (copied)
                                break;
@@ -564,7 +564,8 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
                if (copy_from_user(buf, src, this_len))
                        return -EFAULT;
-               retval = access_process_vm(tsk, dst, buf, this_len, 1);
+               retval = access_process_vm(tsk, dst, buf, this_len,
+                               FOLL_FORCE | FOLL_WRITE);
                if (!retval) {
                        if (copied)
                                break;
@@ -1127,7 +1128,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
        unsigned long tmp;
        int copied;
 
-       copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
+       copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), FOLL_FORCE);
        if (copied != sizeof(tmp))
                return -EIO;
        return put_user(tmp, (unsigned long __user *)data);
@@ -1138,7 +1139,8 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
 {
        int copied;
 
-       copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
+       copied = access_process_vm(tsk, addr, &data, sizeof(data),
+                       FOLL_FORCE | FOLL_WRITE);
        return (copied == sizeof(data)) ? 0 : -EIO;
 }
 
@@ -1155,7 +1157,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
        switch (request) {
        case PTRACE_PEEKTEXT:
        case PTRACE_PEEKDATA:
-               ret = access_process_vm(child, addr, &word, sizeof(word), 0);
+               ret = access_process_vm(child, addr, &word, sizeof(word),
+                               FOLL_FORCE);
                if (ret != sizeof(word))
                        ret = -EIO;
                else
@@ -1164,7 +1167,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 
        case PTRACE_POKETEXT:
        case PTRACE_POKEDATA:
-               ret = access_process_vm(child, addr, &data, sizeof(data), 1);
+               ret = access_process_vm(child, addr, &data, sizeof(data),
+                               FOLL_FORCE | FOLL_WRITE);
                ret = (ret != sizeof(data) ? -EIO : 0);
                break;
 
index 94732d1..42d4027 100644 (file)
@@ -7515,11 +7515,27 @@ static struct kmem_cache *task_group_cache __read_mostly;
 DECLARE_PER_CPU(cpumask_var_t, load_balance_mask);
 DECLARE_PER_CPU(cpumask_var_t, select_idle_mask);
 
+#define WAIT_TABLE_BITS 8
+#define WAIT_TABLE_SIZE (1 << WAIT_TABLE_BITS)
+static wait_queue_head_t bit_wait_table[WAIT_TABLE_SIZE] __cacheline_aligned;
+
+wait_queue_head_t *bit_waitqueue(void *word, int bit)
+{
+       const int shift = BITS_PER_LONG == 32 ? 5 : 6;
+       unsigned long val = (unsigned long)word << shift | bit;
+
+       return bit_wait_table + hash_long(val, WAIT_TABLE_BITS);
+}
+EXPORT_SYMBOL(bit_waitqueue);
+
 void __init sched_init(void)
 {
        int i, j;
        unsigned long alloc_size = 0, ptr;
 
+       for (i = 0; i < WAIT_TABLE_SIZE; i++)
+               init_waitqueue_head(bit_wait_table + i);
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
        alloc_size += 2 * nr_cpu_ids * sizeof(void **);
 #endif
index 2d4ad72..c242944 100644 (file)
@@ -690,7 +690,14 @@ void init_entity_runnable_average(struct sched_entity *se)
         * will definitely be update (after enqueue).
         */
        sa->period_contrib = 1023;
-       sa->load_avg = scale_load_down(se->load.weight);
+       /*
+        * Tasks are intialized with full load to be seen as heavy tasks until
+        * they get a chance to stabilize to their real load level.
+        * Group entities are intialized with zero load to reflect the fact that
+        * nothing has been attached to the task group yet.
+        */
+       if (entity_is_task(se))
+               sa->load_avg = scale_load_down(se->load.weight);
        sa->load_sum = sa->load_avg * LOAD_AVG_MAX;
        /*
         * At this point, util_avg won't be used in select_task_rq_fair anyway
@@ -5471,13 +5478,18 @@ static inline int select_idle_smt(struct task_struct *p, struct sched_domain *sd
  */
 static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int target)
 {
-       struct sched_domain *this_sd = rcu_dereference(*this_cpu_ptr(&sd_llc));
-       u64 avg_idle = this_rq()->avg_idle;
-       u64 avg_cost = this_sd->avg_scan_cost;
+       struct sched_domain *this_sd;
+       u64 avg_cost, avg_idle = this_rq()->avg_idle;
        u64 time, cost;
        s64 delta;
        int cpu, wrap;
 
+       this_sd = rcu_dereference(*this_cpu_ptr(&sd_llc));
+       if (!this_sd)
+               return -1;
+
+       avg_cost = this_sd->avg_scan_cost;
+
        /*
         * Due to large variance we need a large fuzz factor; hackbench in
         * particularly is sensitive here.
@@ -8827,7 +8839,6 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 {
        struct sched_entity *se;
        struct cfs_rq *cfs_rq;
-       struct rq *rq;
        int i;
 
        tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
@@ -8842,8 +8853,6 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
        init_cfs_bandwidth(tg_cfs_bandwidth(tg));
 
        for_each_possible_cpu(i) {
-               rq = cpu_rq(i);
-
                cfs_rq = kzalloc_node(sizeof(struct cfs_rq),
                                      GFP_KERNEL, cpu_to_node(i));
                if (!cfs_rq)
index 4f70535..9453efe 100644 (file)
@@ -480,16 +480,6 @@ void wake_up_bit(void *word, int bit)
 }
 EXPORT_SYMBOL(wake_up_bit);
 
-wait_queue_head_t *bit_waitqueue(void *word, int bit)
-{
-       const int shift = BITS_PER_LONG == 32 ? 5 : 6;
-       const struct zone *zone = page_zone(virt_to_page(word));
-       unsigned long val = (unsigned long)word << shift | bit;
-
-       return &zone->wait_table[hash_long(val, zone->wait_table_bits)];
-}
-EXPORT_SYMBOL(bit_waitqueue);
-
 /*
  * Manipulate the atomic_t address to produce a better bit waitqueue table hash
  * index (we're keying off bit -1, but that would produce a horrible hash
index 1bf81ef..744fa61 100644 (file)
@@ -58,7 +58,7 @@ static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp
 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
 const char * const softirq_to_name[NR_SOFTIRQS] = {
-       "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
+       "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
        "TASKLET", "SCHED", "HRTIMER", "RCU"
 };
 
index c3aad68..12dd190 100644 (file)
@@ -542,7 +542,6 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
 static int alarm_timer_create(struct k_itimer *new_timer)
 {
        enum  alarmtimer_type type;
-       struct alarm_base *base;
 
        if (!alarmtimer_get_rtcdev())
                return -ENOTSUPP;
@@ -551,7 +550,6 @@ static int alarm_timer_create(struct k_itimer *new_timer)
                return -EPERM;
 
        type = clock2alarm(new_timer->it_clock);
-       base = &alarm_bases[type];
        alarm_init(&new_timer->it.alarm.alarmtimer, type, alarm_handle_timer);
        return 0;
 }
index 2d47980..c611c47 100644 (file)
@@ -878,7 +878,7 @@ static inline struct timer_base *get_timer_base(u32 tflags)
 
 #ifdef CONFIG_NO_HZ_COMMON
 static inline struct timer_base *
-__get_target_base(struct timer_base *base, unsigned tflags)
+get_target_base(struct timer_base *base, unsigned tflags)
 {
 #ifdef CONFIG_SMP
        if ((tflags & TIMER_PINNED) || !base->migration_enabled)
@@ -891,25 +891,27 @@ __get_target_base(struct timer_base *base, unsigned tflags)
 
 static inline void forward_timer_base(struct timer_base *base)
 {
+       unsigned long jnow = READ_ONCE(jiffies);
+
        /*
         * We only forward the base when it's idle and we have a delta between
         * base clock and jiffies.
         */
-       if (!base->is_idle || (long) (jiffies - base->clk) < 2)
+       if (!base->is_idle || (long) (jnow - base->clk) < 2)
                return;
 
        /*
         * If the next expiry value is > jiffies, then we fast forward to
         * jiffies otherwise we forward to the next expiry value.
         */
-       if (time_after(base->next_expiry, jiffies))
-               base->clk = jiffies;
+       if (time_after(base->next_expiry, jnow))
+               base->clk = jnow;
        else
                base->clk = base->next_expiry;
 }
 #else
 static inline struct timer_base *
-__get_target_base(struct timer_base *base, unsigned tflags)
+get_target_base(struct timer_base *base, unsigned tflags)
 {
        return get_timer_this_cpu_base(tflags);
 }
@@ -917,14 +919,6 @@ __get_target_base(struct timer_base *base, unsigned tflags)
 static inline void forward_timer_base(struct timer_base *base) { }
 #endif
 
-static inline struct timer_base *
-get_target_base(struct timer_base *base, unsigned tflags)
-{
-       struct timer_base *target = __get_target_base(base, tflags);
-
-       forward_timer_base(target);
-       return target;
-}
 
 /*
  * We are using hashed locking: Holding per_cpu(timer_bases[x]).lock means
@@ -943,7 +937,14 @@ static struct timer_base *lock_timer_base(struct timer_list *timer,
 {
        for (;;) {
                struct timer_base *base;
-               u32 tf = timer->flags;
+               u32 tf;
+
+               /*
+                * We need to use READ_ONCE() here, otherwise the compiler
+                * might re-read @tf between the check for TIMER_MIGRATING
+                * and spin_lock().
+                */
+               tf = READ_ONCE(timer->flags);
 
                if (!(tf & TIMER_MIGRATING)) {
                        base = get_timer_base(tf);
@@ -964,6 +965,8 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
        unsigned long clk = 0, flags;
        int ret = 0;
 
+       BUG_ON(!timer->function);
+
        /*
         * This is a common optimization triggered by the networking code - if
         * the timer is re-modified to have the same timeout or ends up in the
@@ -972,13 +975,16 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
        if (timer_pending(timer)) {
                if (timer->expires == expires)
                        return 1;
+
                /*
-                * Take the current timer_jiffies of base, but without holding
-                * the lock!
+                * We lock timer base and calculate the bucket index right
+                * here. If the timer ends up in the same bucket, then we
+                * just update the expiry time and avoid the whole
+                * dequeue/enqueue dance.
                 */
-               base = get_timer_base(timer->flags);
-               clk = base->clk;
+               base = lock_timer_base(timer, &flags);
 
+               clk = base->clk;
                idx = calc_wheel_index(expires, clk);
 
                /*
@@ -988,14 +994,14 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
                 */
                if (idx == timer_get_idx(timer)) {
                        timer->expires = expires;
-                       return 1;
+                       ret = 1;
+                       goto out_unlock;
                }
+       } else {
+               base = lock_timer_base(timer, &flags);
        }
 
        timer_stats_timer_set_start_info(timer);
-       BUG_ON(!timer->function);
-
-       base = lock_timer_base(timer, &flags);
 
        ret = detach_if_pending(timer, base, false);
        if (!ret && pending_only)
@@ -1025,12 +1031,16 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
                }
        }
 
+       /* Try to forward a stale timer base clock */
+       forward_timer_base(base);
+
        timer->expires = expires;
        /*
         * If 'idx' was calculated above and the base time did not advance
-        * between calculating 'idx' and taking the lock, only enqueue_timer()
-        * and trigger_dyntick_cpu() is required. Otherwise we need to
-        * (re)calculate the wheel index via internal_add_timer().
+        * between calculating 'idx' and possibly switching the base, only
+        * enqueue_timer() and trigger_dyntick_cpu() is required. Otherwise
+        * we need to (re)calculate the wheel index via
+        * internal_add_timer().
         */
        if (idx != UINT_MAX && clk == base->clk) {
                enqueue_timer(base, timer, idx);
@@ -1510,12 +1520,16 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
        is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);
        base->next_expiry = nextevt;
        /*
-        * We have a fresh next event. Check whether we can forward the base:
+        * We have a fresh next event. Check whether we can forward the
+        * base. We can only do that when @basej is past base->clk
+        * otherwise we might rewind base->clk.
         */
-       if (time_after(nextevt, jiffies))
-               base->clk = jiffies;
-       else if (time_after(nextevt, base->clk))
-               base->clk = nextevt;
+       if (time_after(basej, base->clk)) {
+               if (time_after(nextevt, basej))
+                       base->clk = basej;
+               else if (time_after(nextevt, base->clk))
+                       base->clk = nextevt;
+       }
 
        if (time_before_eq(nextevt, basej)) {
                expires = basem;
index 33bc56c..b01e547 100644 (file)
@@ -198,6 +198,7 @@ config FRAME_WARN
        int "Warn for stack frames larger than (needs gcc 4.4)"
        range 0 8192
        default 0 if KASAN
+       default 2048 if GCC_PLUGIN_LATENT_ENTROPY
        default 1024 if !64BIT
        default 2048 if 64BIT
        help
index 0a11396..144fe6b 100644 (file)
@@ -292,7 +292,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size,
        struct gen_pool_chunk *chunk;
        unsigned long addr = 0;
        int order = pool->min_alloc_order;
-       int nbits, start_bit = 0, end_bit, remain;
+       int nbits, start_bit, end_bit, remain;
 
 #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
        BUG_ON(in_nmi());
@@ -307,6 +307,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size,
                if (size > atomic_read(&chunk->avail))
                        continue;
 
+               start_bit = 0;
                end_bit = chunk_size(chunk) >> order;
 retry:
                start_bit = algo(chunk->bits, end_bit, start_bit,
index 60f77f1..4d830e2 100644 (file)
@@ -50,7 +50,7 @@
                                        STACK_ALLOC_ALIGN)
 #define STACK_ALLOC_INDEX_BITS (DEPOT_STACK_BITS - \
                STACK_ALLOC_NULL_PROTECTION_BITS - STACK_ALLOC_OFFSET_BITS)
-#define STACK_ALLOC_SLABS_CAP 1024
+#define STACK_ALLOC_SLABS_CAP 8192
 #define STACK_ALLOC_MAX_SLABS \
        (((1LL << (STACK_ALLOC_INDEX_BITS)) < STACK_ALLOC_SLABS_CAP) ? \
         (1LL << (STACK_ALLOC_INDEX_BITS)) : STACK_ALLOC_SLABS_CAP)
index 94346b4..0362da0 100644 (file)
@@ -4831,7 +4831,7 @@ static struct bpf_test tests[] = {
                { },
                INTERNAL,
                { 0x34 },
-               { { 1, 0xbef } },
+               { { ETH_HLEN, 0xbef } },
                .fill_helper = bpf_fill_ld_abs_vlan_push_pop,
        },
        /*
index be0ee11..86e3e0e 100644 (file)
@@ -187,7 +187,7 @@ config MEMORY_HOTPLUG
        bool "Allow for memory hot-add"
        depends on SPARSEMEM || X86_64_ACPI_NUMA
        depends on ARCH_ENABLE_MEMORY_HOTPLUG
-       depends on !KASAN
+       depends on COMPILE_TEST || !KASAN
 
 config MEMORY_HOTPLUG_SPARSE
        def_bool y
index 849f459..c7fe2f1 100644 (file)
@@ -790,9 +790,7 @@ EXPORT_SYMBOL(__page_cache_alloc);
  */
 wait_queue_head_t *page_waitqueue(struct page *page)
 {
-       const struct zone *zone = page_zone(page);
-
-       return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)];
+       return bit_waitqueue(page, 0);
 }
 EXPORT_SYMBOL(page_waitqueue);
 
index 381bb07..db77dcb 100644 (file)
  * get_vaddr_frames() - map virtual addresses to pfns
  * @start:     starting user address
  * @nr_frames: number of pages / pfns from start to map
- * @write:     whether pages will be written to by the caller
- * @force:     whether to force write access even if user mapping is
- *             readonly. See description of the same argument of
-               get_user_pages().
+ * @gup_flags: flags modifying lookup behaviour
  * @vec:       structure which receives pages / pfns of the addresses mapped.
  *             It should have space for at least nr_frames entries.
  *
@@ -34,7 +31,7 @@
  * This function takes care of grabbing mmap_sem as necessary.
  */
 int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
-                    bool write, bool force, struct frame_vector *vec)
+                    unsigned int gup_flags, struct frame_vector *vec)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
@@ -59,7 +56,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
                vec->got_ref = true;
                vec->is_pfns = false;
                ret = get_user_pages_locked(start, nr_frames,
-                       write, force, (struct page **)(vec->ptrs), &locked);
+                       gup_flags, (struct page **)(vec->ptrs), &locked);
                goto out;
        }
 
index 96b2b2f..ec4f827 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -60,6 +60,16 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address,
        return -EEXIST;
 }
 
+/*
+ * FOLL_FORCE can write to even unwritable pte's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+{
+       return pte_write(pte) ||
+               ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+}
+
 static struct page *follow_page_pte(struct vm_area_struct *vma,
                unsigned long address, pmd_t *pmd, unsigned int flags)
 {
@@ -95,7 +105,7 @@ retry:
        }
        if ((flags & FOLL_NUMA) && pte_protnone(pte))
                goto no_page;
-       if ((flags & FOLL_WRITE) && !pte_write(pte)) {
+       if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
                pte_unmap_unlock(ptep, ptl);
                return NULL;
        }
@@ -412,7 +422,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
         * reCOWed by userspace write).
         */
        if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
-               *flags &= ~FOLL_WRITE;
+               *flags |= FOLL_COW;
        return 0;
 }
 
@@ -516,7 +526,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
  * instead of __get_user_pages. __get_user_pages should be used only if
  * you need some special @gup_flags.
  */
-long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                unsigned long start, unsigned long nr_pages,
                unsigned int gup_flags, struct page **pages,
                struct vm_area_struct **vmas, int *nonblocking)
@@ -621,7 +631,6 @@ next_page:
        } while (nr_pages);
        return i;
 }
-EXPORT_SYMBOL(__get_user_pages);
 
 bool vma_permits_fault(struct vm_area_struct *vma, unsigned int fault_flags)
 {
@@ -729,7 +738,6 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
                                                struct mm_struct *mm,
                                                unsigned long start,
                                                unsigned long nr_pages,
-                                               int write, int force,
                                                struct page **pages,
                                                struct vm_area_struct **vmas,
                                                int *locked, bool notify_drop,
@@ -747,10 +755,6 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
 
        if (pages)
                flags |= FOLL_GET;
-       if (write)
-               flags |= FOLL_WRITE;
-       if (force)
-               flags |= FOLL_FORCE;
 
        pages_done = 0;
        lock_dropped = false;
@@ -843,12 +847,12 @@ static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
  *          up_read(&mm->mmap_sem);
  */
 long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
-                          int write, int force, struct page **pages,
+                          unsigned int gup_flags, struct page **pages,
                           int *locked)
 {
        return __get_user_pages_locked(current, current->mm, start, nr_pages,
-                                      write, force, pages, NULL, locked, true,
-                                      FOLL_TOUCH);
+                                      pages, NULL, locked, true,
+                                      gup_flags | FOLL_TOUCH);
 }
 EXPORT_SYMBOL(get_user_pages_locked);
 
@@ -864,14 +868,14 @@ EXPORT_SYMBOL(get_user_pages_locked);
  */
 __always_inline long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
                                               unsigned long start, unsigned long nr_pages,
-                                              int write, int force, struct page **pages,
-                                              unsigned int gup_flags)
+                                              struct page **pages, unsigned int gup_flags)
 {
        long ret;
        int locked = 1;
+
        down_read(&mm->mmap_sem);
-       ret = __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-                                     pages, NULL, &locked, false, gup_flags);
+       ret = __get_user_pages_locked(tsk, mm, start, nr_pages, pages, NULL,
+                                     &locked, false, gup_flags);
        if (locked)
                up_read(&mm->mmap_sem);
        return ret;
@@ -896,10 +900,10 @@ EXPORT_SYMBOL(__get_user_pages_unlocked);
  * "force" parameter).
  */
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
-                            int write, int force, struct page **pages)
+                            struct page **pages, unsigned int gup_flags)
 {
        return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
-                                        write, force, pages, FOLL_TOUCH);
+                                        pages, gup_flags | FOLL_TOUCH);
 }
 EXPORT_SYMBOL(get_user_pages_unlocked);
 
@@ -910,9 +914,7 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
  * @mm:                mm_struct of target mm
  * @start:     starting user address
  * @nr_pages:  number of pages from start to pin
- * @write:     whether pages will be written to by the caller
- * @force:     whether to force access even when user mapping is currently
- *             protected (but never forces write access to shared mapping).
+ * @gup_flags: flags modifying lookup behaviour
  * @pages:     array that receives pointers to the pages pinned.
  *             Should be at least nr_pages long. Or NULL, if caller
  *             only intends to ensure the pages are faulted in.
@@ -941,9 +943,9 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
  * or similar operation cannot guarantee anything stronger anyway because
  * locks can't be held over the syscall boundary.
  *
- * If write=0, the page must not be written to. If the page is written to,
- * set_page_dirty (or set_page_dirty_lock, as appropriate) must be called
- * after the page is finished with, and before put_page is called.
+ * If gup_flags & FOLL_WRITE == 0, the page must not be written to. If the page
+ * is written to, set_page_dirty (or set_page_dirty_lock, as appropriate) must
+ * be called after the page is finished with, and before put_page is called.
  *
  * get_user_pages is typically used for fewer-copy IO operations, to get a
  * handle on the memory by some means other than accesses via the user virtual
@@ -960,12 +962,12 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
  */
 long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
                unsigned long start, unsigned long nr_pages,
-               int write, int force, struct page **pages,
+               unsigned int gup_flags, struct page **pages,
                struct vm_area_struct **vmas)
 {
-       return __get_user_pages_locked(tsk, mm, start, nr_pages, write, force,
-                                      pages, vmas, NULL, false,
-                                      FOLL_TOUCH | FOLL_REMOTE);
+       return __get_user_pages_locked(tsk, mm, start, nr_pages, pages, vmas,
+                                      NULL, false,
+                                      gup_flags | FOLL_TOUCH | FOLL_REMOTE);
 }
 EXPORT_SYMBOL(get_user_pages_remote);
 
@@ -976,12 +978,12 @@ EXPORT_SYMBOL(get_user_pages_remote);
  * obviously don't pass FOLL_REMOTE in here.
  */
 long get_user_pages(unsigned long start, unsigned long nr_pages,
-               int write, int force, struct page **pages,
+               unsigned int gup_flags, struct page **pages,
                struct vm_area_struct **vmas)
 {
        return __get_user_pages_locked(current, current->mm, start, nr_pages,
-                                      write, force, pages, vmas, NULL, false,
-                                      FOLL_TOUCH);
+                                      pages, vmas, NULL, false,
+                                      gup_flags | FOLL_TOUCH);
 }
 EXPORT_SYMBOL(get_user_pages);
 
@@ -1505,7 +1507,8 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                start += nr << PAGE_SHIFT;
                pages += nr;
 
-               ret = get_user_pages_unlocked(start, nr_pages - nr, write, 0, pages);
+               ret = get_user_pages_unlocked(start, nr_pages - nr, pages,
+                               write ? FOLL_WRITE : 0);
 
                /* Have to be a bit careful with return values */
                if (nr > 0) {
index 88af13c..70c0097 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
+#include <linux/bug.h>
 
 #include "kasan.h"
 #include "../slab.h"
@@ -62,7 +63,7 @@ void kasan_unpoison_shadow(const void *address, size_t size)
        }
 }
 
-static void __kasan_unpoison_stack(struct task_struct *task, void *sp)
+static void __kasan_unpoison_stack(struct task_struct *task, const void *sp)
 {
        void *base = task_stack_page(task);
        size_t size = sp - base;
@@ -77,9 +78,24 @@ void kasan_unpoison_task_stack(struct task_struct *task)
 }
 
 /* Unpoison the stack for the current task beyond a watermark sp value. */
-asmlinkage void kasan_unpoison_remaining_stack(void *sp)
+asmlinkage void kasan_unpoison_task_stack_below(const void *watermark)
 {
-       __kasan_unpoison_stack(current, sp);
+       __kasan_unpoison_stack(current, watermark);
+}
+
+/*
+ * Clear all poison for the region between the current SP and a provided
+ * watermark value, as is sometimes required prior to hand-crafted asm function
+ * returns in the middle of functions.
+ */
+void kasan_unpoison_stack_above_sp_to(const void *watermark)
+{
+       const void *sp = __builtin_frame_address(0);
+       size_t size = watermark - sp;
+
+       if (WARN_ON(sp > watermark))
+               return;
+       kasan_unpoison_shadow(sp, size);
 }
 
 /*
index a5e453c..e5355a5 100644 (file)
@@ -1453,8 +1453,11 @@ static void kmemleak_scan(void)
 
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
-                       scan_block(task_stack_page(p), task_stack_page(p) +
-                                  THREAD_SIZE, NULL);
+                       void *stack = try_get_task_stack(p);
+                       if (stack) {
+                               scan_block(stack, stack + THREAD_SIZE, NULL);
+                               put_task_stack(p);
+                       }
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
        }
index 1d05cb9..234676e 100644 (file)
@@ -554,6 +554,8 @@ int __list_lru_init(struct list_lru *lru, bool memcg_aware,
        err = memcg_init_list_lru(lru, memcg_aware);
        if (err) {
                kfree(lru->node);
+               /* Do this so a list_lru_destroy() doesn't crash: */
+               lru->node = NULL;
                goto out;
        }
 
index ae052b5..0f870ba 100644 (file)
@@ -1917,6 +1917,15 @@ retry:
                     current->flags & PF_EXITING))
                goto force;
 
+       /*
+        * Prevent unbounded recursion when reclaim operations need to
+        * allocate memory. This might exceed the limits temporarily,
+        * but we prefer facilitating memory reclaim and getting back
+        * under the limit over triggering OOM kills in these cases.
+        */
+       if (unlikely(current->flags & PF_MEMALLOC))
+               goto force;
+
        if (unlikely(task_in_memcg_oom(current)))
                goto nomem;
 
index fc1987d..e18c57b 100644 (file)
@@ -3869,10 +3869,11 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
  * given task for page fault accounting.
  */
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long addr, void *buf, int len, int write)
+               unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
        struct vm_area_struct *vma;
        void *old_buf = buf;
+       int write = gup_flags & FOLL_WRITE;
 
        down_read(&mm->mmap_sem);
        /* ignore errors, just check how much was successfully transferred */
@@ -3882,7 +3883,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
                struct page *page = NULL;
 
                ret = get_user_pages_remote(tsk, mm, addr, 1,
-                               write, 1, &page, &vma);
+                               gup_flags, &page, &vma);
                if (ret <= 0) {
 #ifndef CONFIG_HAVE_IOREMAP_PROT
                        break;
@@ -3934,14 +3935,14 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
  * @addr:      start address to access
  * @buf:       source or destination buffer
  * @len:       number of bytes to transfer
- * @write:     whether the access is a write
+ * @gup_flags: flags modifying lookup behaviour
  *
  * The caller must hold a reference on @mm.
  */
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-               void *buf, int len, int write)
+               void *buf, int len, unsigned int gup_flags)
 {
-       return __access_remote_vm(NULL, mm, addr, buf, len, write);
+       return __access_remote_vm(NULL, mm, addr, buf, len, gup_flags);
 }
 
 /*
@@ -3950,7 +3951,7 @@ int access_remote_vm(struct mm_struct *mm, unsigned long addr,
  * Do not walk the page table directly, use get_user_pages
  */
 int access_process_vm(struct task_struct *tsk, unsigned long addr,
-               void *buf, int len, int write)
+               void *buf, int len, unsigned int gup_flags)
 {
        struct mm_struct *mm;
        int ret;
@@ -3959,7 +3960,8 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr,
        if (!mm)
                return 0;
 
-       ret = __access_remote_vm(tsk, mm, addr, buf, len, write);
+       ret = __access_remote_vm(tsk, mm, addr, buf, len, gup_flags);
+
        mmput(mm);
 
        return ret;
index 9629273..cad4b91 100644 (file)
@@ -268,7 +268,6 @@ void __init register_page_bootmem_info_node(struct pglist_data *pgdat)
        unsigned long i, pfn, end_pfn, nr_pages;
        int node = pgdat->node_id;
        struct page *page;
-       struct zone *zone;
 
        nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT;
        page = virt_to_page(pgdat);
@@ -276,19 +275,6 @@ void __init register_page_bootmem_info_node(struct pglist_data *pgdat)
        for (i = 0; i < nr_pages; i++, page++)
                get_page_bootmem(node, page, NODE_INFO);
 
-       zone = &pgdat->node_zones[0];
-       for (; zone < pgdat->node_zones + MAX_NR_ZONES - 1; zone++) {
-               if (zone_is_initialized(zone)) {
-                       nr_pages = zone->wait_table_hash_nr_entries
-                               * sizeof(wait_queue_head_t);
-                       nr_pages = PAGE_ALIGN(nr_pages) >> PAGE_SHIFT;
-                       page = virt_to_page(zone->wait_table);
-
-                       for (i = 0; i < nr_pages; i++, page++)
-                               get_page_bootmem(node, page, NODE_INFO);
-               }
-       }
-
        pfn = pgdat->node_start_pfn;
        end_pfn = pgdat_end_pfn(pgdat);
 
@@ -2131,7 +2117,6 @@ void try_offline_node(int nid)
        unsigned long start_pfn = pgdat->node_start_pfn;
        unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
        unsigned long pfn;
-       int i;
 
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
                unsigned long section_nr = pfn_to_section_nr(pfn);
@@ -2158,20 +2143,6 @@ void try_offline_node(int nid)
         */
        node_set_offline(nid);
        unregister_one_node(nid);
-
-       /* free waittable in each zone */
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               struct zone *zone = pgdat->node_zones + i;
-
-               /*
-                * wait_table may be allocated from boot memory,
-                * here only free if it's allocated by vmalloc.
-                */
-               if (is_vmalloc_addr(zone->wait_table)) {
-                       vfree(zone->wait_table);
-                       zone->wait_table = NULL;
-               }
-       }
 }
 EXPORT_SYMBOL(try_offline_node);
 
index ad1c96a..0b859af 100644 (file)
@@ -850,7 +850,7 @@ static int lookup_node(unsigned long addr)
        struct page *p;
        int err;
 
-       err = get_user_pages(addr & PAGE_MASK, 1, 0, 0, &p, NULL);
+       err = get_user_pages(addr & PAGE_MASK, 1, 0, &p, NULL);
        if (err >= 0) {
                err = page_to_nid(p);
                put_page(p);
index bcdbe62..1193652 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/perf_event.h>
 #include <linux/pkeys.h>
 #include <linux/ksm.h>
-#include <linux/pkeys.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
index 95daf81..8b8faaf 100644 (file)
@@ -109,7 +109,7 @@ unsigned int kobjsize(const void *objp)
        return PAGE_SIZE << compound_order(page);
 }
 
-long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                      unsigned long start, unsigned long nr_pages,
                      unsigned int foll_flags, struct page **pages,
                      struct vm_area_struct **vmas, int *nonblocking)
@@ -160,33 +160,25 @@ finish_or_fault:
  * - don't permit access to VMAs that don't support it, such as I/O mappings
  */
 long get_user_pages(unsigned long start, unsigned long nr_pages,
-                   int write, int force, struct page **pages,
+                   unsigned int gup_flags, struct page **pages,
                    struct vm_area_struct **vmas)
 {
-       int flags = 0;
-
-       if (write)
-               flags |= FOLL_WRITE;
-       if (force)
-               flags |= FOLL_FORCE;
-
-       return __get_user_pages(current, current->mm, start, nr_pages, flags,
-                               pages, vmas, NULL);
+       return __get_user_pages(current, current->mm, start, nr_pages,
+                               gup_flags, pages, vmas, NULL);
 }
 EXPORT_SYMBOL(get_user_pages);
 
 long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
-                           int write, int force, struct page **pages,
+                           unsigned int gup_flags, struct page **pages,
                            int *locked)
 {
-       return get_user_pages(start, nr_pages, write, force, pages, NULL);
+       return get_user_pages(start, nr_pages, gup_flags, pages, NULL);
 }
 EXPORT_SYMBOL(get_user_pages_locked);
 
 long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
                               unsigned long start, unsigned long nr_pages,
-                              int write, int force, struct page **pages,
-                              unsigned int gup_flags)
+                              struct page **pages, unsigned int gup_flags)
 {
        long ret;
        down_read(&mm->mmap_sem);
@@ -198,10 +190,10 @@ long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
 EXPORT_SYMBOL(__get_user_pages_unlocked);
 
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
-                            int write, int force, struct page **pages)
+                            struct page **pages, unsigned int gup_flags)
 {
        return __get_user_pages_unlocked(current, current->mm, start, nr_pages,
-                                        write, force, pages, 0);
+                                        pages, gup_flags);
 }
 EXPORT_SYMBOL(get_user_pages_unlocked);
 
@@ -1817,9 +1809,10 @@ void filemap_map_pages(struct fault_env *fe,
 EXPORT_SYMBOL(filemap_map_pages);
 
 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long addr, void *buf, int len, int write)
+               unsigned long addr, void *buf, int len, unsigned int gup_flags)
 {
        struct vm_area_struct *vma;
+       int write = gup_flags & FOLL_WRITE;
 
        down_read(&mm->mmap_sem);
 
@@ -1854,21 +1847,22 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
  * @addr:      start address to access
  * @buf:       source or destination buffer
  * @len:       number of bytes to transfer
- * @write:     whether the access is a write
+ * @gup_flags: flags modifying lookup behaviour
  *
  * The caller must hold a reference on @mm.
  */
 int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-               void *buf, int len, int write)
+               void *buf, int len, unsigned int gup_flags)
 {
-       return __access_remote_vm(NULL, mm, addr, buf, len, write);
+       return __access_remote_vm(NULL, mm, addr, buf, len, gup_flags);
 }
 
 /*
  * Access another process' address space.
  * - source/target buffer must be kernel space
  */
-int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len,
+               unsigned int gup_flags)
 {
        struct mm_struct *mm;
 
@@ -1879,7 +1873,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
        if (!mm)
                return 0;
 
-       len = __access_remote_vm(tsk, mm, addr, buf, len, write);
+       len = __access_remote_vm(tsk, mm, addr, buf, len, gup_flags);
 
        mmput(mm);
        return len;
index 2b3bf67..8fd42aa 100644 (file)
@@ -4224,7 +4224,7 @@ static void show_migration_types(unsigned char type)
        }
 
        *p = '\0';
-       printk("(%s) ", tmp);
+       printk(KERN_CONT "(%s) ", tmp);
 }
 
 /*
@@ -4335,7 +4335,8 @@ void show_free_areas(unsigned int filter)
                        free_pcp += per_cpu_ptr(zone->pageset, cpu)->pcp.count;
 
                show_node(zone);
-               printk("%s"
+               printk(KERN_CONT
+                       "%s"
                        " free:%lukB"
                        " min:%lukB"
                        " low:%lukB"
@@ -4382,8 +4383,8 @@ void show_free_areas(unsigned int filter)
                        K(zone_page_state(zone, NR_FREE_CMA_PAGES)));
                printk("lowmem_reserve[]:");
                for (i = 0; i < MAX_NR_ZONES; i++)
-                       printk(" %ld", zone->lowmem_reserve[i]);
-               printk("\n");
+                       printk(KERN_CONT " %ld", zone->lowmem_reserve[i]);
+               printk(KERN_CONT "\n");
        }
 
        for_each_populated_zone(zone) {
@@ -4394,7 +4395,7 @@ void show_free_areas(unsigned int filter)
                if (skip_free_areas_node(filter, zone_to_nid(zone)))
                        continue;
                show_node(zone);
-               printk("%s: ", zone->name);
+               printk(KERN_CONT "%s: ", zone->name);
 
                spin_lock_irqsave(&zone->lock, flags);
                for (order = 0; order < MAX_ORDER; order++) {
@@ -4412,11 +4413,12 @@ void show_free_areas(unsigned int filter)
                }
                spin_unlock_irqrestore(&zone->lock, flags);
                for (order = 0; order < MAX_ORDER; order++) {
-                       printk("%lu*%lukB ", nr[order], K(1UL) << order);
+                       printk(KERN_CONT "%lu*%lukB ",
+                              nr[order], K(1UL) << order);
                        if (nr[order])
                                show_migration_types(types[order]);
                }
-               printk("= %lukB\n", K(total));
+               printk(KERN_CONT "= %lukB\n", K(total));
        }
 
        hugetlb_show_meminfo();
@@ -4976,72 +4978,6 @@ void __ref build_all_zonelists(pg_data_t *pgdat, struct zone *zone)
 #endif
 }
 
-/*
- * Helper functions to size the waitqueue hash table.
- * Essentially these want to choose hash table sizes sufficiently
- * large so that collisions trying to wait on pages are rare.
- * But in fact, the number of active page waitqueues on typical
- * systems is ridiculously low, less than 200. So this is even
- * conservative, even though it seems large.
- *
- * The constant PAGES_PER_WAITQUEUE specifies the ratio of pages to
- * waitqueues, i.e. the size of the waitq table given the number of pages.
- */
-#define PAGES_PER_WAITQUEUE    256
-
-#ifndef CONFIG_MEMORY_HOTPLUG
-static inline unsigned long wait_table_hash_nr_entries(unsigned long pages)
-{
-       unsigned long size = 1;
-
-       pages /= PAGES_PER_WAITQUEUE;
-
-       while (size < pages)
-               size <<= 1;
-
-       /*
-        * Once we have dozens or even hundreds of threads sleeping
-        * on IO we've got bigger problems than wait queue collision.
-        * Limit the size of the wait table to a reasonable size.
-        */
-       size = min(size, 4096UL);
-
-       return max(size, 4UL);
-}
-#else
-/*
- * A zone's size might be changed by hot-add, so it is not possible to determine
- * a suitable size for its wait_table.  So we use the maximum size now.
- *
- * The max wait table size = 4096 x sizeof(wait_queue_head_t).   ie:
- *
- *    i386 (preemption config)    : 4096 x 16 = 64Kbyte.
- *    ia64, x86-64 (no preemption): 4096 x 20 = 80Kbyte.
- *    ia64, x86-64 (preemption)   : 4096 x 24 = 96Kbyte.
- *
- * The maximum entries are prepared when a zone's memory is (512K + 256) pages
- * or more by the traditional way. (See above).  It equals:
- *
- *    i386, x86-64, powerpc(4K page size) : =  ( 2G + 1M)byte.
- *    ia64(16K page size)                 : =  ( 8G + 4M)byte.
- *    powerpc (64K page size)             : =  (32G +16M)byte.
- */
-static inline unsigned long wait_table_hash_nr_entries(unsigned long pages)
-{
-       return 4096UL;
-}
-#endif
-
-/*
- * This is an integer logarithm so that shifts can be used later
- * to extract the more random high bits from the multiplicative
- * hash function before the remainder is taken.
- */
-static inline unsigned long wait_table_bits(unsigned long size)
-{
-       return ffz(~size);
-}
-
 /*
  * Initially all pages are reserved - free ones are freed
  * up by free_all_bootmem() once the early boot process is
@@ -5304,49 +5240,6 @@ void __init setup_per_cpu_pageset(void)
                        alloc_percpu(struct per_cpu_nodestat);
 }
 
-static noinline __ref
-int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
-{
-       int i;
-       size_t alloc_size;
-
-       /*
-        * The per-page waitqueue mechanism uses hashed waitqueues
-        * per zone.
-        */
-       zone->wait_table_hash_nr_entries =
-                wait_table_hash_nr_entries(zone_size_pages);
-       zone->wait_table_bits =
-               wait_table_bits(zone->wait_table_hash_nr_entries);
-       alloc_size = zone->wait_table_hash_nr_entries
-                                       * sizeof(wait_queue_head_t);
-
-       if (!slab_is_available()) {
-               zone->wait_table = (wait_queue_head_t *)
-                       memblock_virt_alloc_node_nopanic(
-                               alloc_size, zone->zone_pgdat->node_id);
-       } else {
-               /*
-                * This case means that a zone whose size was 0 gets new memory
-                * via memory hot-add.
-                * But it may be the case that a new node was hot-added.  In
-                * this case vmalloc() will not be able to use this new node's
-                * memory - this wait_table must be initialized to use this new
-                * node itself as well.
-                * To use this new node's memory, further consideration will be
-                * necessary.
-                */
-               zone->wait_table = vmalloc(alloc_size);
-       }
-       if (!zone->wait_table)
-               return -ENOMEM;
-
-       for (i = 0; i < zone->wait_table_hash_nr_entries; ++i)
-               init_waitqueue_head(zone->wait_table + i);
-
-       return 0;
-}
-
 static __meminit void zone_pcp_init(struct zone *zone)
 {
        /*
@@ -5367,10 +5260,7 @@ int __meminit init_currently_empty_zone(struct zone *zone,
                                        unsigned long size)
 {
        struct pglist_data *pgdat = zone->zone_pgdat;
-       int ret;
-       ret = zone_wait_table_init(zone, size);
-       if (ret)
-               return ret;
+
        pgdat->nr_zones = zone_idx(zone) + 1;
 
        zone->zone_start_pfn = zone_start_pfn;
@@ -5382,6 +5272,7 @@ int __meminit init_currently_empty_zone(struct zone *zone,
                        zone_start_pfn, (zone_start_pfn + size));
 
        zone_init_free_lists(zone);
+       zone->initialized = 1;
 
        return 0;
 }
index 07514d4..be8dc8d 100644 (file)
@@ -88,12 +88,16 @@ static int process_vm_rw_single_vec(unsigned long addr,
        ssize_t rc = 0;
        unsigned long max_pages_per_loop = PVM_MAX_KMALLOC_PAGES
                / sizeof(struct pages *);
+       unsigned int flags = FOLL_REMOTE;
 
        /* Work out address and page range required */
        if (len == 0)
                return 0;
        nr_pages = (addr + len - 1) / PAGE_SIZE - addr / PAGE_SIZE + 1;
 
+       if (vm_write)
+               flags |= FOLL_WRITE;
+
        while (!rc && nr_pages && iov_iter_count(iter)) {
                int pages = min(nr_pages, max_pages_per_loop);
                size_t bytes;
@@ -104,8 +108,7 @@ static int process_vm_rw_single_vec(unsigned long addr,
                 * current/current->mm
                 */
                pages = __get_user_pages_unlocked(task, mm, pa, pages,
-                                                 vm_write, 0, process_pages,
-                                                 FOLL_REMOTE);
+                                                 process_pages, flags);
                if (pages <= 0)
                        return -EFAULT;
 
index 090fb26..0b0550c 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -233,6 +233,7 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent)
        spin_lock_init(&parent->list_lock);
        parent->free_objects = 0;
        parent->free_touched = 0;
+       parent->num_slabs = 0;
 }
 
 #define MAKE_LIST(cachep, listp, slab, nodeid)                         \
@@ -966,7 +967,7 @@ static int setup_kmem_cache_node(struct kmem_cache *cachep,
         * guaranteed to be valid until irq is re-enabled, because it will be
         * freed after synchronize_sched().
         */
-       if (force_change)
+       if (old_shared && force_change)
                synchronize_sched();
 
 fail:
@@ -1382,24 +1383,27 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
        for_each_kmem_cache_node(cachep, node, n) {
                unsigned long active_objs = 0, num_objs = 0, free_objects = 0;
                unsigned long active_slabs = 0, num_slabs = 0;
+               unsigned long num_slabs_partial = 0, num_slabs_free = 0;
+               unsigned long num_slabs_full;
 
                spin_lock_irqsave(&n->list_lock, flags);
-               list_for_each_entry(page, &n->slabs_full, lru) {
-                       active_objs += cachep->num;
-                       active_slabs++;
-               }
+               num_slabs = n->num_slabs;
                list_for_each_entry(page, &n->slabs_partial, lru) {
                        active_objs += page->active;
-                       active_slabs++;
+                       num_slabs_partial++;
                }
                list_for_each_entry(page, &n->slabs_free, lru)
-                       num_slabs++;
+                       num_slabs_free++;
 
                free_objects += n->free_objects;
                spin_unlock_irqrestore(&n->list_lock, flags);
 
-               num_slabs += active_slabs;
                num_objs = num_slabs * cachep->num;
+               active_slabs = num_slabs - num_slabs_free;
+               num_slabs_full = num_slabs -
+                       (num_slabs_partial + num_slabs_free);
+               active_objs += (num_slabs_full * cachep->num);
+
                pr_warn("  node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
                        node, active_slabs, num_slabs, active_objs, num_objs,
                        free_objects);
@@ -2314,6 +2318,7 @@ static int drain_freelist(struct kmem_cache *cache,
 
                page = list_entry(p, struct page, lru);
                list_del(&page->lru);
+               n->num_slabs--;
                /*
                 * Safe to drop the lock. The slab is no longer linked
                 * to the cache.
@@ -2752,6 +2757,8 @@ static void cache_grow_end(struct kmem_cache *cachep, struct page *page)
                list_add_tail(&page->lru, &(n->slabs_free));
        else
                fixup_slab_list(cachep, n, page, &list);
+
+       n->num_slabs++;
        STATS_INC_GROWN(cachep);
        n->free_objects += cachep->num - page->active;
        spin_unlock(&n->list_lock);
@@ -3443,6 +3450,7 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
 
                page = list_last_entry(&n->slabs_free, struct page, lru);
                list_move(&page->lru, list);
+               n->num_slabs--;
        }
 }
 
@@ -4099,6 +4107,8 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
        unsigned long num_objs;
        unsigned long active_slabs = 0;
        unsigned long num_slabs, free_objects = 0, shared_avail = 0;
+       unsigned long num_slabs_partial = 0, num_slabs_free = 0;
+       unsigned long num_slabs_full = 0;
        const char *name;
        char *error = NULL;
        int node;
@@ -4111,33 +4121,34 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
                check_irq_on();
                spin_lock_irq(&n->list_lock);
 
-               list_for_each_entry(page, &n->slabs_full, lru) {
-                       if (page->active != cachep->num && !error)
-                               error = "slabs_full accounting error";
-                       active_objs += cachep->num;
-                       active_slabs++;
-               }
+               num_slabs += n->num_slabs;
+
                list_for_each_entry(page, &n->slabs_partial, lru) {
                        if (page->active == cachep->num && !error)
                                error = "slabs_partial accounting error";
                        if (!page->active && !error)
                                error = "slabs_partial accounting error";
                        active_objs += page->active;
-                       active_slabs++;
+                       num_slabs_partial++;
                }
+
                list_for_each_entry(page, &n->slabs_free, lru) {
                        if (page->active && !error)
                                error = "slabs_free accounting error";
-                       num_slabs++;
+                       num_slabs_free++;
                }
+
                free_objects += n->free_objects;
                if (n->shared)
                        shared_avail += n->shared->avail;
 
                spin_unlock_irq(&n->list_lock);
        }
-       num_slabs += active_slabs;
        num_objs = num_slabs * cachep->num;
+       active_slabs = num_slabs - num_slabs_free;
+       num_slabs_full = num_slabs - (num_slabs_partial + num_slabs_free);
+       active_objs += (num_slabs_full * cachep->num);
+
        if (num_objs - active_objs != free_objects && !error)
                error = "free_objects accounting error";
 
index 9653f2e..bc05fdc 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -432,6 +432,7 @@ struct kmem_cache_node {
        struct list_head slabs_partial; /* partial list first, better asm code */
        struct list_head slabs_full;
        struct list_head slabs_free;
+       unsigned long num_slabs;
        unsigned long free_objects;
        unsigned int free_limit;
        unsigned int colour_next;       /* Per-node cache coloring */
index 662cddf..1a41553 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -230,8 +230,10 @@ void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
 }
 
 /* Check if the vma is being used as a stack by this task */
-int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t)
+int vma_is_stack_for_current(struct vm_area_struct *vma)
 {
+       struct task_struct * __maybe_unused t = current;
+
        return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
 }
 
@@ -283,7 +285,8 @@ EXPORT_SYMBOL_GPL(__get_user_pages_fast);
 int __weak get_user_pages_fast(unsigned long start,
                                int nr_pages, int write, struct page **pages)
 {
-       return get_user_pages_unlocked(start, nr_pages, write, 0, pages);
+       return get_user_pages_unlocked(start, nr_pages, pages,
+                                      write ? FOLL_WRITE : 0);
 }
 EXPORT_SYMBOL_GPL(get_user_pages_fast);
 
@@ -623,7 +626,7 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
        if (len > buflen)
                len = buflen;
 
-       res = access_process_vm(task, arg_start, buffer, len, 0);
+       res = access_process_vm(task, arg_start, buffer, len, FOLL_FORCE);
 
        /*
         * If the nul at the end of args has been overwritten, then
@@ -638,7 +641,8 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
                        if (len > buflen - res)
                                len = buflen - res;
                        res += access_process_vm(task, env_start,
-                                                buffer+res, len, 0);
+                                                buffer+res, len,
+                                                FOLL_FORCE);
                        res = strnlen(buffer, res);
                }
        }
index 744f926..76fda22 100644 (file)
@@ -3043,7 +3043,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                                            sc.gfp_mask,
                                            sc.reclaim_idx);
 
+       current->flags |= PF_MEMALLOC;
        nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
+       current->flags &= ~PF_MEMALLOC;
 
        trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
index 8de138d..f2531ad 100644 (file)
@@ -664,7 +664,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
 
        skb_gro_pull(skb, sizeof(*vhdr));
        skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
-       pp = ptype->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
        rcu_read_unlock();
index 08ce361..e034afb 100644 (file)
@@ -652,7 +652,6 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
                        batadv_softif_destroy_sysfs(hard_iface->soft_iface);
        }
 
-       hard_iface->soft_iface = NULL;
        batadv_hardif_put(hard_iface);
 
 out:
index e0e1a88..d2905a8 100644 (file)
@@ -63,7 +63,7 @@ enum batadv_dbg_level {
        BATADV_DBG_NC           = BIT(5),
        BATADV_DBG_MCAST        = BIT(6),
        BATADV_DBG_TP_METER     = BIT(7),
-       BATADV_DBG_ALL          = 127,
+       BATADV_DBG_ALL          = 255,
 };
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
index 5f3bfc4..7c8d160 100644 (file)
@@ -544,7 +544,7 @@ batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface,
        if (bat_priv->algo_ops->neigh.hardif_init)
                bat_priv->algo_ops->neigh.hardif_init(hardif_neigh);
 
-       hlist_add_head(&hardif_neigh->list, &hard_iface->neigh_list);
+       hlist_add_head_rcu(&hardif_neigh->list, &hard_iface->neigh_list);
 
 out:
        spin_unlock_bh(&hard_iface->neigh_list_lock);
index e228842..1015d9c 100644 (file)
@@ -969,41 +969,38 @@ void __hci_req_enable_advertising(struct hci_request *req)
        hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
 }
 
-static u8 append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
+u8 append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
 {
-       size_t complete_len;
        size_t short_len;
-       int max_len;
-
-       max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
-       complete_len = strlen(hdev->dev_name);
-       short_len = strlen(hdev->short_name);
-
-       /* no space left for name */
-       if (max_len < 1)
-               return ad_len;
+       size_t complete_len;
 
-       /* no name set */
-       if (!complete_len)
+       /* no space left for name (+ NULL + type + len) */
+       if ((HCI_MAX_AD_LENGTH - ad_len) < HCI_MAX_SHORT_NAME_LENGTH + 3)
                return ad_len;
 
-       /* complete name fits and is eq to max short name len or smaller */
-       if (complete_len <= max_len &&
-           complete_len <= HCI_MAX_SHORT_NAME_LENGTH) {
+       /* use complete name if present and fits */
+       complete_len = strlen(hdev->dev_name);
+       if (complete_len && complete_len <= HCI_MAX_SHORT_NAME_LENGTH)
                return eir_append_data(ptr, ad_len, EIR_NAME_COMPLETE,
-                                      hdev->dev_name, complete_len);
-       }
+                                      hdev->dev_name, complete_len + 1);
 
-       /* short name set and fits */
-       if (short_len && short_len <= max_len) {
+       /* use short name if present */
+       short_len = strlen(hdev->short_name);
+       if (short_len)
                return eir_append_data(ptr, ad_len, EIR_NAME_SHORT,
-                                      hdev->short_name, short_len);
-       }
+                                      hdev->short_name, short_len + 1);
 
-       /* no short name set so shorten complete name */
-       if (!short_len) {
-               return eir_append_data(ptr, ad_len, EIR_NAME_SHORT,
-                                      hdev->dev_name, max_len);
+       /* use shortened full name if present, we already know that name
+        * is longer then HCI_MAX_SHORT_NAME_LENGTH
+        */
+       if (complete_len) {
+               u8 name[HCI_MAX_SHORT_NAME_LENGTH + 1];
+
+               memcpy(name, hdev->dev_name, HCI_MAX_SHORT_NAME_LENGTH);
+               name[HCI_MAX_SHORT_NAME_LENGTH] = '\0';
+
+               return eir_append_data(ptr, ad_len, EIR_NAME_SHORT, name,
+                                      sizeof(name));
        }
 
        return ad_len;
index 6b06629..dde77bd 100644 (file)
@@ -106,6 +106,8 @@ static inline void hci_update_background_scan(struct hci_dev *hdev)
 void hci_request_setup(struct hci_dev *hdev);
 void hci_request_cancel_all(struct hci_dev *hdev);
 
+u8 append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len);
+
 static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type,
                                  u8 *data, u8 data_len)
 {
index 7360380..1fba2a0 100644 (file)
@@ -6017,7 +6017,15 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
        return err;
 }
 
-static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
+static u8 calculate_name_len(struct hci_dev *hdev)
+{
+       u8 buf[HCI_MAX_SHORT_NAME_LENGTH + 3];
+
+       return append_local_name(hdev, buf, 0);
+}
+
+static u8 tlv_data_max_len(struct hci_dev *hdev, u32 adv_flags,
+                          bool is_adv_data)
 {
        u8 max_len = HCI_MAX_AD_LENGTH;
 
@@ -6030,9 +6038,8 @@ static u8 tlv_data_max_len(u32 adv_flags, bool is_adv_data)
                if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
                        max_len -= 3;
        } else {
-               /* at least 1 byte of name should fit in */
                if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
-                       max_len -= 3;
+                       max_len -= calculate_name_len(hdev);
 
                if (adv_flags & (MGMT_ADV_FLAG_APPEARANCE))
                        max_len -= 4;
@@ -6063,12 +6070,13 @@ static bool appearance_managed(u32 adv_flags)
        return adv_flags & MGMT_ADV_FLAG_APPEARANCE;
 }
 
-static bool tlv_data_is_valid(u32 adv_flags, u8 *data, u8 len, bool is_adv_data)
+static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
+                             u8 len, bool is_adv_data)
 {
        int i, cur_len;
        u8 max_len;
 
-       max_len = tlv_data_max_len(adv_flags, is_adv_data);
+       max_len = tlv_data_max_len(hdev, adv_flags, is_adv_data);
 
        if (len > max_len)
                return false;
@@ -6215,8 +6223,8 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
                goto unlock;
        }
 
-       if (!tlv_data_is_valid(flags, cp->data, cp->adv_data_len, true) ||
-           !tlv_data_is_valid(flags, cp->data + cp->adv_data_len,
+       if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
+           !tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
                               cp->scan_rsp_len, false)) {
                err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
                                      MGMT_STATUS_INVALID_PARAMS);
@@ -6429,8 +6437,8 @@ static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev,
 
        rp.instance = cp->instance;
        rp.flags = cp->flags;
-       rp.max_adv_data_len = tlv_data_max_len(flags, true);
-       rp.max_scan_rsp_len = tlv_data_max_len(flags, false);
+       rp.max_adv_data_len = tlv_data_max_len(hdev, flags, true);
+       rp.max_scan_rsp_len = tlv_data_max_len(hdev, flags, false);
 
        err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
                                MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
index c5fea93..2136e45 100644 (file)
@@ -972,13 +972,12 @@ static void br_multicast_enable(struct bridge_mcast_own_query *query)
                mod_timer(&query->timer, jiffies);
 }
 
-void br_multicast_enable_port(struct net_bridge_port *port)
+static void __br_multicast_enable_port(struct net_bridge_port *port)
 {
        struct net_bridge *br = port->br;
 
-       spin_lock(&br->multicast_lock);
        if (br->multicast_disabled || !netif_running(br->dev))
-               goto out;
+               return;
 
        br_multicast_enable(&port->ip4_own_query);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -987,8 +986,14 @@ void br_multicast_enable_port(struct net_bridge_port *port)
        if (port->multicast_router == MDB_RTR_TYPE_PERM &&
            hlist_unhashed(&port->rlist))
                br_multicast_add_router(br, port);
+}
 
-out:
+void br_multicast_enable_port(struct net_bridge_port *port)
+{
+       struct net_bridge *br = port->br;
+
+       spin_lock(&br->multicast_lock);
+       __br_multicast_enable_port(port);
        spin_unlock(&br->multicast_lock);
 }
 
@@ -1994,8 +1999,9 @@ static void br_multicast_start_querier(struct net_bridge *br,
 
 int br_multicast_toggle(struct net_bridge *br, unsigned long val)
 {
-       int err = 0;
        struct net_bridge_mdb_htable *mdb;
+       struct net_bridge_port *port;
+       int err = 0;
 
        spin_lock_bh(&br->multicast_lock);
        if (br->multicast_disabled == !val)
@@ -2023,10 +2029,9 @@ rollback:
                        goto rollback;
        }
 
-       br_multicast_start_querier(br, &br->ip4_own_query);
-#if IS_ENABLED(CONFIG_IPV6)
-       br_multicast_start_querier(br, &br->ip6_own_query);
-#endif
+       br_multicast_open(br);
+       list_for_each_entry(port, &br->port_list, list)
+               __br_multicast_enable_port(port);
 
 unlock:
        spin_unlock_bh(&br->multicast_lock);
index 00d2601..1a7c9a7 100644 (file)
@@ -26,7 +26,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
        while (got < num_pages) {
                rc = get_user_pages_unlocked(
                    (unsigned long)data + ((unsigned long)got * PAGE_SIZE),
-                   num_pages - got, write_page, 0, pages + got);
+                   num_pages - got, pages + got, write_page ? FOLL_WRITE : 0);
                if (rc < 0)
                        break;
                BUG_ON(rc == 0);
index 4bc19a1..820bac2 100644 (file)
@@ -3035,6 +3035,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
        }
        return head;
 }
+EXPORT_SYMBOL_GPL(validate_xmit_skb_list);
 
 static void qdisc_pkt_len_init(struct sk_buff *skb)
 {
@@ -4511,6 +4512,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
                NAPI_GRO_CB(skb)->encap_mark = 0;
+               NAPI_GRO_CB(skb)->recursion_counter = 0;
                NAPI_GRO_CB(skb)->is_fou = 0;
                NAPI_GRO_CB(skb)->is_atomic = 1;
                NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
@@ -5511,10 +5513,14 @@ struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
 {
        struct netdev_adjacent *lower;
 
-       lower = list_first_or_null_rcu(&dev->all_adj_list.lower,
-                                      struct netdev_adjacent, list);
+       lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
+
+       if (&lower->list == &dev->all_adj_list.lower)
+               return NULL;
+
+       *iter = &lower->list;
 
-       return lower ? lower->dev : NULL;
+       return lower->dev;
 }
 EXPORT_SYMBOL(netdev_all_lower_get_next_rcu);
 
index 1a7b80f..ab193e5 100644 (file)
@@ -246,15 +246,13 @@ ipv6:
        case htons(ETH_P_8021AD):
        case htons(ETH_P_8021Q): {
                const struct vlan_hdr *vlan;
+               struct vlan_hdr _vlan;
+               bool vlan_tag_present = skb && skb_vlan_tag_present(skb);
 
-               if (skb_vlan_tag_present(skb))
+               if (vlan_tag_present)
                        proto = skb->protocol;
 
-               if (!skb_vlan_tag_present(skb) ||
-                   proto == cpu_to_be16(ETH_P_8021Q) ||
-                   proto == cpu_to_be16(ETH_P_8021AD)) {
-                       struct vlan_hdr _vlan;
-
+               if (!vlan_tag_present || eth_type_vlan(skb->protocol)) {
                        vlan = __skb_header_pointer(skb, nhoff, sizeof(_vlan),
                                                    data, hlen, &_vlan);
                        if (!vlan)
@@ -272,7 +270,7 @@ ipv6:
                                                             FLOW_DISSECTOR_KEY_VLAN,
                                                             target_container);
 
-                       if (skb_vlan_tag_present(skb)) {
+                       if (vlan_tag_present) {
                                key_vlan->vlan_id = skb_vlan_tag_get_id(skb);
                                key_vlan->vlan_priority =
                                        (skb_vlan_tag_get_prio(skb) >> VLAN_PRIO_SHIFT);
index 989434f..f61c0e0 100644 (file)
@@ -215,13 +215,14 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id);
  */
 int peernet2id_alloc(struct net *net, struct net *peer)
 {
+       unsigned long flags;
        bool alloc;
        int id;
 
-       spin_lock_bh(&net->nsid_lock);
+       spin_lock_irqsave(&net->nsid_lock, flags);
        alloc = atomic_read(&peer->count) == 0 ? false : true;
        id = __peernet2id_alloc(net, peer, &alloc);
-       spin_unlock_bh(&net->nsid_lock);
+       spin_unlock_irqrestore(&net->nsid_lock, flags);
        if (alloc && id >= 0)
                rtnl_net_notifyid(net, RTM_NEWNSID, id);
        return id;
@@ -230,11 +231,12 @@ int peernet2id_alloc(struct net *net, struct net *peer)
 /* This function returns, if assigned, the id of a peer netns. */
 int peernet2id(struct net *net, struct net *peer)
 {
+       unsigned long flags;
        int id;
 
-       spin_lock_bh(&net->nsid_lock);
+       spin_lock_irqsave(&net->nsid_lock, flags);
        id = __peernet2id(net, peer);
-       spin_unlock_bh(&net->nsid_lock);
+       spin_unlock_irqrestore(&net->nsid_lock, flags);
        return id;
 }
 EXPORT_SYMBOL(peernet2id);
@@ -249,17 +251,18 @@ bool peernet_has_id(struct net *net, struct net *peer)
 
 struct net *get_net_ns_by_id(struct net *net, int id)
 {
+       unsigned long flags;
        struct net *peer;
 
        if (id < 0)
                return NULL;
 
        rcu_read_lock();
-       spin_lock_bh(&net->nsid_lock);
+       spin_lock_irqsave(&net->nsid_lock, flags);
        peer = idr_find(&net->netns_ids, id);
        if (peer)
                get_net(peer);
-       spin_unlock_bh(&net->nsid_lock);
+       spin_unlock_irqrestore(&net->nsid_lock, flags);
        rcu_read_unlock();
 
        return peer;
@@ -422,17 +425,17 @@ static void cleanup_net(struct work_struct *work)
                for_each_net(tmp) {
                        int id;
 
-                       spin_lock_bh(&tmp->nsid_lock);
+                       spin_lock_irq(&tmp->nsid_lock);
                        id = __peernet2id(tmp, net);
                        if (id >= 0)
                                idr_remove(&tmp->netns_ids, id);
-                       spin_unlock_bh(&tmp->nsid_lock);
+                       spin_unlock_irq(&tmp->nsid_lock);
                        if (id >= 0)
                                rtnl_net_notifyid(tmp, RTM_DELNSID, id);
                }
-               spin_lock_bh(&net->nsid_lock);
+               spin_lock_irq(&net->nsid_lock);
                idr_destroy(&net->netns_ids);
-               spin_unlock_bh(&net->nsid_lock);
+               spin_unlock_irq(&net->nsid_lock);
 
        }
        rtnl_unlock();
@@ -561,6 +564,7 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        struct net *net = sock_net(skb->sk);
        struct nlattr *tb[NETNSA_MAX + 1];
+       unsigned long flags;
        struct net *peer;
        int nsid, err;
 
@@ -581,15 +585,15 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (IS_ERR(peer))
                return PTR_ERR(peer);
 
-       spin_lock_bh(&net->nsid_lock);
+       spin_lock_irqsave(&net->nsid_lock, flags);
        if (__peernet2id(net, peer) >= 0) {
-               spin_unlock_bh(&net->nsid_lock);
+               spin_unlock_irqrestore(&net->nsid_lock, flags);
                err = -EEXIST;
                goto out;
        }
 
        err = alloc_netid(net, peer, nsid);
-       spin_unlock_bh(&net->nsid_lock);
+       spin_unlock_irqrestore(&net->nsid_lock, flags);
        if (err >= 0) {
                rtnl_net_notifyid(net, RTM_NEWNSID, err);
                err = 0;
@@ -711,10 +715,11 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
                .idx = 0,
                .s_idx = cb->args[0],
        };
+       unsigned long flags;
 
-       spin_lock_bh(&net->nsid_lock);
+       spin_lock_irqsave(&net->nsid_lock, flags);
        idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
-       spin_unlock_bh(&net->nsid_lock);
+       spin_unlock_irqrestore(&net->nsid_lock, flags);
 
        cb->args[0] = net_cb.idx;
        return skb->len;
index 5219a9e..306b8f0 100644 (file)
 #define M_QUEUE_XMIT           2       /* Inject packet into qdisc */
 
 /* If lock -- protects updating of if_list */
-#define   if_lock(t)           spin_lock(&(t->if_lock));
-#define   if_unlock(t)           spin_unlock(&(t->if_lock));
+#define   if_lock(t)           mutex_lock(&(t->if_lock));
+#define   if_unlock(t)           mutex_unlock(&(t->if_lock));
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
@@ -423,7 +423,7 @@ struct pktgen_net {
 };
 
 struct pktgen_thread {
-       spinlock_t if_lock;             /* for list of devices */
+       struct mutex if_lock;           /* for list of devices */
        struct list_head if_list;       /* All device here */
        struct list_head th_list;
        struct task_struct *tsk;
@@ -2010,11 +2010,13 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d
 {
        struct pktgen_thread *t;
 
+       mutex_lock(&pktgen_thread_lock);
+
        list_for_each_entry(t, &pn->pktgen_threads, th_list) {
                struct pktgen_dev *pkt_dev;
 
-               rcu_read_lock();
-               list_for_each_entry_rcu(pkt_dev, &t->if_list, list) {
+               if_lock(t);
+               list_for_each_entry(pkt_dev, &t->if_list, list) {
                        if (pkt_dev->odev != dev)
                                continue;
 
@@ -2029,8 +2031,9 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d
                                       dev->name);
                        break;
                }
-               rcu_read_unlock();
+               if_unlock(t);
        }
+       mutex_unlock(&pktgen_thread_lock);
 }
 
 static int pktgen_device_event(struct notifier_block *unused,
@@ -3762,7 +3765,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
                return -ENOMEM;
        }
 
-       spin_lock_init(&t->if_lock);
+       mutex_init(&t->if_lock);
        t->cpu = cpu;
 
        INIT_LIST_HEAD(&t->if_list);
index e92b759..9a1a352 100644 (file)
@@ -129,7 +129,6 @@ int reuseport_add_sock(struct sock *sk, struct sock *sk2)
 
        return 0;
 }
-EXPORT_SYMBOL(reuseport_add_sock);
 
 static void reuseport_free_rcu(struct rcu_head *head)
 {
index 66dff5e..02acfff 100644 (file)
@@ -439,7 +439,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head,
 
        skb_gro_pull(skb, sizeof(*eh));
        skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
-       pp = ptype->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
 
 out_unlock:
        rcu_read_unlock();
index 5ee1d43..4ebe2aa 100644 (file)
@@ -300,10 +300,6 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
 static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb,
                             struct hsr_frame_info *frame)
 {
-       struct net_device *master_dev;
-
-       master_dev = hsr_port_get_hsr(hsr, HSR_PT_MASTER)->dev;
-
        if (hsr_addr_is_self(hsr, eth_hdr(skb)->h_dest)) {
                frame->is_local_exclusive = true;
                skb->pkt_type = PACKET_HOST;
index 1effc98..9648c97 100644 (file)
@@ -1391,7 +1391,7 @@ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        skb_gro_pull(skb, sizeof(*iph));
        skb_set_transport_header(skb, skb_gro_offset(skb));
 
-       pp = ops->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
        rcu_read_unlock();
index cf50f7e..030d153 100644 (file)
@@ -249,7 +249,7 @@ static struct sk_buff **fou_gro_receive(struct sock *sk,
        if (!ops || !ops->callbacks.gro_receive)
                goto out_unlock;
 
-       pp = ops->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
        rcu_read_unlock();
@@ -441,7 +441,7 @@ next_proto:
        if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
                goto out_unlock;
 
-       pp = ops->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
        flush = 0;
 
 out_unlock:
index 96e0efe..d5cac99 100644 (file)
@@ -229,7 +229,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
        /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
        skb_gro_postpull_rcsum(skb, greh, grehlen);
 
-       pp = ptype->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
        flush = 0;
 
 out_unlock:
index 77c20a4..ca97835 100644 (file)
@@ -25,6 +25,7 @@
 #include <net/inet_hashtables.h>
 #include <net/secure_seq.h>
 #include <net/ip.h>
+#include <net/tcp.h>
 #include <net/sock_reuseport.h>
 
 static u32 inet_ehashfn(const struct net *net, const __be32 laddr,
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(__inet_inherit_port);
 
 static inline int compute_score(struct sock *sk, struct net *net,
                                const unsigned short hnum, const __be32 daddr,
-                               const int dif)
+                               const int dif, bool exact_dif)
 {
        int score = -1;
        struct inet_sock *inet = inet_sk(sk);
@@ -186,7 +187,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                                return -1;
                        score += 4;
                }
-               if (sk->sk_bound_dev_if) {
+               if (sk->sk_bound_dev_if || exact_dif) {
                        if (sk->sk_bound_dev_if != dif)
                                return -1;
                        score += 4;
@@ -215,11 +216,12 @@ struct sock *__inet_lookup_listener(struct net *net,
        unsigned int hash = inet_lhashfn(net, hnum);
        struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
        int score, hiscore = 0, matches = 0, reuseport = 0;
+       bool exact_dif = inet_exact_dif_match(net, skb);
        struct sock *sk, *result = NULL;
        u32 phash = 0;
 
        sk_for_each_rcu(sk, &ilb->head) {
-               score = compute_score(sk, net, hnum, daddr, dif);
+               score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
                if (score > hiscore) {
                        reuseport = sk->sk_reuseport;
                        if (reuseport) {
index 05d1058..03e7f73 100644 (file)
@@ -538,7 +538,6 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 {
        struct iphdr *iph;
        int ptr;
-       struct net_device *dev;
        struct sk_buff *skb2;
        unsigned int mtu, hlen, left, len, ll_rs;
        int offset;
@@ -546,8 +545,6 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
        struct rtable *rt = skb_rtable(skb);
        int err = 0;
 
-       dev = rt->dst.dev;
-
        /* for offloaded checksums cleanup checksum before fragmentation */
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
            (err = skb_checksum_help(skb)))
index af49197..b8a2d63 100644 (file)
@@ -98,7 +98,7 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
 }
 
 static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
-                                 int offset)
+                                 int tlen, int offset)
 {
        __wsum csum = skb->csum;
 
@@ -106,8 +106,9 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
                return;
 
        if (offset != 0)
-               csum = csum_sub(csum, csum_partial(skb_transport_header(skb),
-                                                  offset, 0));
+               csum = csum_sub(csum,
+                               csum_partial(skb_transport_header(skb) + tlen,
+                                            offset, 0));
 
        put_cmsg(msg, SOL_IP, IP_CHECKSUM, sizeof(__wsum), &csum);
 }
@@ -153,7 +154,7 @@ static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
 }
 
 void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
-                        int offset)
+                        int tlen, int offset)
 {
        struct inet_sock *inet = inet_sk(skb->sk);
        unsigned int flags = inet->cmsg_flags;
@@ -216,7 +217,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,
        }
 
        if (flags & IP_CMSG_CHECKSUM)
-               ip_cmsg_recv_checksum(msg, skb, offset);
+               ip_cmsg_recv_checksum(msg, skb, tlen, offset);
 }
 EXPORT_SYMBOL(ip_cmsg_recv_offset);
 
index 7cf7d6e..205e200 100644 (file)
@@ -994,7 +994,7 @@ struct proto ping_prot = {
        .init =         ping_init_sock,
        .close =        ping_close,
        .connect =      ip4_datagram_connect,
-       .disconnect =   udp_disconnect,
+       .disconnect =   __udp_disconnect,
        .setsockopt =   ip_setsockopt,
        .getsockopt =   ip_getsockopt,
        .sendmsg =      ping_v4_sendmsg,
index 90a85c9..ecbe5a7 100644 (file)
@@ -918,7 +918,7 @@ struct proto raw_prot = {
        .close             = raw_close,
        .destroy           = raw_destroy,
        .connect           = ip4_datagram_connect,
-       .disconnect        = udp_disconnect,
+       .disconnect        = __udp_disconnect,
        .ioctl             = raw_ioctl,
        .init              = raw_init,
        .setsockopt        = raw_setsockopt,
index 1cb67de..80bc36b 100644 (file)
@@ -96,11 +96,11 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low
                container_of(table->data, struct net, ipv4.ping_group_range.range);
        unsigned int seq;
        do {
-               seq = read_seqbegin(&net->ipv4.ip_local_ports.lock);
+               seq = read_seqbegin(&net->ipv4.ping_group_range.lock);
 
                *low = data[0];
                *high = data[1];
-       } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));
+       } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq));
 }
 
 /* Update system visible IP port range */
@@ -109,10 +109,10 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig
        kgid_t *data = table->data;
        struct net *net =
                container_of(table->data, struct net, ipv4.ping_group_range.range);
-       write_seqlock(&net->ipv4.ip_local_ports.lock);
+       write_seqlock(&net->ipv4.ping_group_range.lock);
        data[0] = low;
        data[1] = high;
-       write_sequnlock(&net->ipv4.ip_local_ports.lock);
+       write_sequnlock(&net->ipv4.ping_group_range.lock);
 }
 
 /* Validate changes from /proc interface. */
index bd5e8d1..61b7be3 100644 (file)
@@ -86,7 +86,6 @@
 
 int sysctl_tcp_tw_reuse __read_mostly;
 int sysctl_tcp_low_latency __read_mostly;
-EXPORT_SYMBOL(sysctl_tcp_low_latency);
 
 #ifdef CONFIG_TCP_MD5SIG
 static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
@@ -1887,7 +1886,6 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
        struct tcp_iter_state *st = seq->private;
        struct net *net = seq_file_net(seq);
        struct inet_listen_hashbucket *ilb;
-       struct inet_connection_sock *icsk;
        struct sock *sk = cur;
 
        if (!sk) {
@@ -1909,7 +1907,6 @@ get_sk:
                        continue;
                if (sk->sk_family == st->family)
                        return sk;
-               icsk = inet_csk(sk);
        }
        spin_unlock_bh(&ilb->lock);
        st->offset = 0;
index 7d96dc2..d123d68 100644 (file)
@@ -1322,7 +1322,7 @@ try_again:
                *addr_len = sizeof(*sin);
        }
        if (inet->cmsg_flags)
-               ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr) + off);
+               ip_cmsg_recv_offset(msg, skb, sizeof(struct udphdr), off);
 
        err = copied;
        if (flags & MSG_TRUNC)
@@ -1345,7 +1345,7 @@ csum_copy_err:
        goto try_again;
 }
 
-int udp_disconnect(struct sock *sk, int flags)
+int __udp_disconnect(struct sock *sk, int flags)
 {
        struct inet_sock *inet = inet_sk(sk);
        /*
@@ -1367,6 +1367,15 @@ int udp_disconnect(struct sock *sk, int flags)
        sk_dst_reset(sk);
        return 0;
 }
+EXPORT_SYMBOL(__udp_disconnect);
+
+int udp_disconnect(struct sock *sk, int flags)
+{
+       lock_sock(sk);
+       __udp_disconnect(sk, flags);
+       release_sock(sk);
+       return 0;
+}
 EXPORT_SYMBOL(udp_disconnect);
 
 void udp_lib_unhash(struct sock *sk)
@@ -2193,7 +2202,7 @@ int udp_abort(struct sock *sk, int err)
 
        sk->sk_err = err;
        sk->sk_error_report(sk);
-       udp_disconnect(sk, 0);
+       __udp_disconnect(sk, 0);
 
        release_sock(sk);
 
index f9333c9..b2be1d9 100644 (file)
@@ -295,7 +295,7 @@ unflush:
 
        skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */
        skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr));
-       pp = udp_sk(sk)->gro_receive(sk, head, skb);
+       pp = call_gro_receive_sk(udp_sk(sk)->gro_receive, sk, head, skb);
 
 out_unlock:
        rcu_read_unlock();
index d8983e1..060dd99 100644 (file)
@@ -147,9 +147,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
 }
 #endif
 
-static void __ipv6_regen_rndid(struct inet6_dev *idev);
-static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
-static void ipv6_regen_rndid(unsigned long data);
+static void ipv6_regen_rndid(struct inet6_dev *idev);
+static void ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
 
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
 static int ipv6_count_addresses(struct inet6_dev *idev);
@@ -409,9 +408,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
                goto err_release;
        }
 
-       /* One reference from device.  We must do this before
-        * we invoke __ipv6_regen_rndid().
-        */
+       /* One reference from device. */
        in6_dev_hold(ndev);
 
        if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
@@ -425,17 +422,15 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 #endif
 
        INIT_LIST_HEAD(&ndev->tempaddr_list);
-       setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev);
+       ndev->desync_factor = U32_MAX;
        if ((dev->flags&IFF_LOOPBACK) ||
            dev->type == ARPHRD_TUNNEL ||
            dev->type == ARPHRD_TUNNEL6 ||
            dev->type == ARPHRD_SIT ||
            dev->type == ARPHRD_NONE) {
                ndev->cnf.use_tempaddr = -1;
-       } else {
-               in6_dev_hold(ndev);
-               ipv6_regen_rndid((unsigned long) ndev);
-       }
+       } else
+               ipv6_regen_rndid(ndev);
 
        ndev->token = in6addr_any;
 
@@ -447,7 +442,6 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
        err = addrconf_sysctl_register(ndev);
        if (err) {
                ipv6_mc_destroy_dev(ndev);
-               del_timer(&ndev->regen_timer);
                snmp6_unregister_dev(ndev);
                goto err_release;
        }
@@ -1190,6 +1184,8 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
        int ret = 0;
        u32 addr_flags;
        unsigned long now = jiffies;
+       long max_desync_factor;
+       s32 cnf_temp_preferred_lft;
 
        write_lock_bh(&idev->lock);
        if (ift) {
@@ -1222,23 +1218,42 @@ retry:
        }
        in6_ifa_hold(ifp);
        memcpy(addr.s6_addr, ifp->addr.s6_addr, 8);
-       __ipv6_try_regen_rndid(idev, tmpaddr);
+       ipv6_try_regen_rndid(idev, tmpaddr);
        memcpy(&addr.s6_addr[8], idev->rndid, 8);
        age = (now - ifp->tstamp) / HZ;
+
+       regen_advance = idev->cnf.regen_max_retry *
+                       idev->cnf.dad_transmits *
+                       NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
+
+       /* recalculate max_desync_factor each time and update
+        * idev->desync_factor if it's larger
+        */
+       cnf_temp_preferred_lft = READ_ONCE(idev->cnf.temp_prefered_lft);
+       max_desync_factor = min_t(__u32,
+                                 idev->cnf.max_desync_factor,
+                                 cnf_temp_preferred_lft - regen_advance);
+
+       if (unlikely(idev->desync_factor > max_desync_factor)) {
+               if (max_desync_factor > 0) {
+                       get_random_bytes(&idev->desync_factor,
+                                        sizeof(idev->desync_factor));
+                       idev->desync_factor %= max_desync_factor;
+               } else {
+                       idev->desync_factor = 0;
+               }
+       }
+
        tmp_valid_lft = min_t(__u32,
                              ifp->valid_lft,
                              idev->cnf.temp_valid_lft + age);
-       tmp_prefered_lft = min_t(__u32,
-                                ifp->prefered_lft,
-                                idev->cnf.temp_prefered_lft + age -
-                                idev->cnf.max_desync_factor);
+       tmp_prefered_lft = cnf_temp_preferred_lft + age -
+                           idev->desync_factor;
+       tmp_prefered_lft = min_t(__u32, ifp->prefered_lft, tmp_prefered_lft);
        tmp_plen = ifp->prefix_len;
        tmp_tstamp = ifp->tstamp;
        spin_unlock_bh(&ifp->lock);
 
-       regen_advance = idev->cnf.regen_max_retry *
-                       idev->cnf.dad_transmits *
-                       NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
        write_unlock_bh(&idev->lock);
 
        /* A temporary address is created only if this calculated Preferred
@@ -2150,7 +2165,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
 }
 
 /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
-static void __ipv6_regen_rndid(struct inet6_dev *idev)
+static void ipv6_regen_rndid(struct inet6_dev *idev)
 {
 regen:
        get_random_bytes(idev->rndid, sizeof(idev->rndid));
@@ -2179,43 +2194,10 @@ regen:
        }
 }
 
-static void ipv6_regen_rndid(unsigned long data)
-{
-       struct inet6_dev *idev = (struct inet6_dev *) data;
-       unsigned long expires;
-
-       rcu_read_lock_bh();
-       write_lock_bh(&idev->lock);
-
-       if (idev->dead)
-               goto out;
-
-       __ipv6_regen_rndid(idev);
-
-       expires = jiffies +
-               idev->cnf.temp_prefered_lft * HZ -
-               idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
-               NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
-               idev->cnf.max_desync_factor * HZ;
-       if (time_before(expires, jiffies)) {
-               pr_warn("%s: too short regeneration interval; timer disabled for %s\n",
-                       __func__, idev->dev->name);
-               goto out;
-       }
-
-       if (!mod_timer(&idev->regen_timer, expires))
-               in6_dev_hold(idev);
-
-out:
-       write_unlock_bh(&idev->lock);
-       rcu_read_unlock_bh();
-       in6_dev_put(idev);
-}
-
-static void  __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
+static void  ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr)
 {
        if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0)
-               __ipv6_regen_rndid(idev);
+               ipv6_regen_rndid(idev);
 }
 
 /*
@@ -2356,7 +2338,7 @@ static void manage_tempaddrs(struct inet6_dev *idev,
                        max_valid = 0;
 
                max_prefered = idev->cnf.temp_prefered_lft -
-                              idev->cnf.max_desync_factor - age;
+                              idev->desync_factor - age;
                if (max_prefered < 0)
                        max_prefered = 0;
 
@@ -3018,7 +3000,7 @@ static void init_loopback(struct net_device *dev)
                                 * lo device down, release this obsolete dst and
                                 * reallocate a new router for ifa.
                                 */
-                               if (sp_ifa->rt->dst.obsolete > 0) {
+                               if (!atomic_read(&sp_ifa->rt->rt6i_ref)) {
                                        ip6_rt_put(sp_ifa->rt);
                                        sp_ifa->rt = NULL;
                                } else {
@@ -3594,9 +3576,6 @@ restart:
        if (!how)
                idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY);
 
-       if (how && del_timer(&idev->regen_timer))
-               in6_dev_put(idev);
-
        /* Step 3: clear tempaddr list */
        while (!list_empty(&idev->tempaddr_list)) {
                ifa = list_first_entry(&idev->tempaddr_list,
index 00cf28a..02761c9 100644 (file)
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__inet6_lookup_established);
 static inline int compute_score(struct sock *sk, struct net *net,
                                const unsigned short hnum,
                                const struct in6_addr *daddr,
-                               const int dif)
+                               const int dif, bool exact_dif)
 {
        int score = -1;
 
@@ -109,7 +109,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
                                return -1;
                        score++;
                }
-               if (sk->sk_bound_dev_if) {
+               if (sk->sk_bound_dev_if || exact_dif) {
                        if (sk->sk_bound_dev_if != dif)
                                return -1;
                        score++;
@@ -131,11 +131,12 @@ struct sock *inet6_lookup_listener(struct net *net,
        unsigned int hash = inet_lhashfn(net, hnum);
        struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
        int score, hiscore = 0, matches = 0, reuseport = 0;
+       bool exact_dif = inet6_exact_dif_match(net, skb);
        struct sock *sk, *result = NULL;
        u32 phash = 0;
 
        sk_for_each(sk, &ilb->head) {
-               score = compute_score(sk, net, hnum, daddr, dif);
+               score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
                if (score > hiscore) {
                        reuseport = sk->sk_reuseport;
                        if (reuseport) {
@@ -263,13 +264,15 @@ EXPORT_SYMBOL_GPL(inet6_hash_connect);
 
 int inet6_hash(struct sock *sk)
 {
+       int err = 0;
+
        if (sk->sk_state != TCP_CLOSE) {
                local_bh_disable();
-               __inet_hash(sk, NULL, ipv6_rcv_saddr_equal);
+               err = __inet_hash(sk, NULL, ipv6_rcv_saddr_equal);
                local_bh_enable();
        }
 
-       return 0;
+       return err;
 }
 EXPORT_SYMBOL_GPL(inet6_hash);
 
index e7bfd55..1fcf61f 100644 (file)
@@ -246,7 +246,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
 
        skb_gro_postpull_rcsum(skb, iph, nlen);
 
-       pp = ops->callbacks.gro_receive(head, skb);
+       pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
 
 out_unlock:
        rcu_read_unlock();
index 6a66adb..8778456 100644 (file)
@@ -157,6 +157,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
        hash = HASH(&any, local);
        for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
                if (ipv6_addr_equal(local, &t->parms.laddr) &&
+                   ipv6_addr_any(&t->parms.raddr) &&
                    (t->dev->flags & IFF_UP))
                        return t;
        }
@@ -164,6 +165,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_
        hash = HASH(remote, &any);
        for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
                if (ipv6_addr_equal(remote, &t->parms.raddr) &&
+                   ipv6_addr_any(&t->parms.laddr) &&
                    (t->dev->flags & IFF_UP))
                        return t;
        }
@@ -1170,6 +1172,7 @@ route_lookup:
        if (err)
                return err;
 
+       skb->protocol = htons(ETH_P_IPV6);
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
index 5330262..636ec56 100644 (file)
@@ -120,6 +120,7 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
 static bool setsockopt_needs_rtnl(int optname)
 {
        switch (optname) {
+       case IPV6_ADDRFORM:
        case IPV6_ADD_MEMBERSHIP:
        case IPV6_DROP_MEMBERSHIP:
        case IPV6_JOIN_ANYCAST:
@@ -198,7 +199,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                        }
 
                        fl6_free_socklist(sk);
-                       ipv6_sock_mc_close(sk);
+                       __ipv6_sock_mc_close(sk);
 
                        /*
                         * Sock is moving from IPv6 to IPv4 (sk_prot), so
index 75c1fc5..14a3903 100644 (file)
@@ -276,16 +276,14 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
        return idev;
 }
 
-void ipv6_sock_mc_close(struct sock *sk)
+void __ipv6_sock_mc_close(struct sock *sk)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct ipv6_mc_socklist *mc_lst;
        struct net *net = sock_net(sk);
 
-       if (!rcu_access_pointer(np->ipv6_mc_list))
-               return;
+       ASSERT_RTNL();
 
-       rtnl_lock();
        while ((mc_lst = rtnl_dereference(np->ipv6_mc_list)) != NULL) {
                struct net_device *dev;
 
@@ -303,8 +301,17 @@ void ipv6_sock_mc_close(struct sock *sk)
 
                atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
                kfree_rcu(mc_lst, rcu);
-
        }
+}
+
+void ipv6_sock_mc_close(struct sock *sk)
+{
+       struct ipv6_pinfo *np = inet6_sk(sk);
+
+       if (!rcu_access_pointer(np->ipv6_mc_list))
+               return;
+       rtnl_lock();
+       __ipv6_sock_mc_close(sk);
        rtnl_unlock();
 }
 
index 0e983b6..66e2d9d 100644 (file)
@@ -180,7 +180,7 @@ struct proto pingv6_prot = {
        .init =         ping_init_sock,
        .close =        ping_close,
        .connect =      ip6_datagram_connect_v6_only,
-       .disconnect =   udp_disconnect,
+       .disconnect =   __udp_disconnect,
        .setsockopt =   ipv6_setsockopt,
        .getsockopt =   ipv6_getsockopt,
        .sendmsg =      ping_v6_sendmsg,
index 54404f0..054a1d8 100644 (file)
@@ -1241,7 +1241,7 @@ struct proto rawv6_prot = {
        .close             = rawv6_close,
        .destroy           = raw6_destroy,
        .connect           = ip6_datagram_connect_v6_only,
-       .disconnect        = udp_disconnect,
+       .disconnect        = __udp_disconnect,
        .ioctl             = rawv6_ioctl,
        .init              = rawv6_init_sk,
        .setsockopt        = rawv6_setsockopt,
index 2160d5d..3815e85 100644 (file)
@@ -456,7 +456,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
        skb_network_header(head)[nhoff] = skb_transport_header(head)[0];
        memmove(head->head + sizeof(struct frag_hdr), head->head,
                (head->data - head->head) - sizeof(struct frag_hdr));
-       head->mac_header += sizeof(struct frag_hdr);
+       if (skb_mac_header_was_set(head))
+               head->mac_header += sizeof(struct frag_hdr);
        head->network_header += sizeof(struct frag_hdr);
 
        skb_reset_transport_header(head);
index bdbc38e..947ed1d 100644 (file)
@@ -102,11 +102,13 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
 #ifdef CONFIG_IPV6_ROUTE_INFO
 static struct rt6_info *rt6_add_route_info(struct net *net,
                                           const struct in6_addr *prefix, int prefixlen,
-                                          const struct in6_addr *gwaddr, int ifindex,
+                                          const struct in6_addr *gwaddr,
+                                          struct net_device *dev,
                                           unsigned int pref);
 static struct rt6_info *rt6_get_route_info(struct net *net,
                                           const struct in6_addr *prefix, int prefixlen,
-                                          const struct in6_addr *gwaddr, int ifindex);
+                                          const struct in6_addr *gwaddr,
+                                          struct net_device *dev);
 #endif
 
 struct uncached_list {
@@ -656,7 +658,8 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
        struct net_device *dev = rt->dst.dev;
 
        if (dev && !netif_carrier_ok(dev) &&
-           idev->cnf.ignore_routes_with_linkdown)
+           idev->cnf.ignore_routes_with_linkdown &&
+           !(strict & RT6_LOOKUP_F_IGNORE_LINKSTATE))
                goto out;
 
        if (rt6_check_expired(rt))
@@ -803,7 +806,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
                rt = rt6_get_dflt_router(gwaddr, dev);
        else
                rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
-                                       gwaddr, dev->ifindex);
+                                       gwaddr, dev);
 
        if (rt && !lifetime) {
                ip6_del_rt(rt);
@@ -811,8 +814,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
        }
 
        if (!rt && lifetime)
-               rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
-                                       pref);
+               rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr,
+                                       dev, pref);
        else if (rt)
                rt->rt6i_flags = RTF_ROUTEINFO |
                                 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
@@ -1050,6 +1053,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
        int strict = 0;
 
        strict |= flags & RT6_LOOKUP_F_IFACE;
+       strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
        if (net->ipv6.devconf_all->forwarding == 0)
                strict |= RT6_LOOKUP_F_REACHABLE;
 
@@ -1789,7 +1793,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
        };
        struct fib6_table *table;
        struct rt6_info *rt;
-       int flags = RT6_LOOKUP_F_IFACE;
+       int flags = RT6_LOOKUP_F_IFACE | RT6_LOOKUP_F_IGNORE_LINKSTATE;
 
        table = fib6_get_table(net, cfg->fc_table);
        if (!table)
@@ -2325,13 +2329,16 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
 #ifdef CONFIG_IPV6_ROUTE_INFO
 static struct rt6_info *rt6_get_route_info(struct net *net,
                                           const struct in6_addr *prefix, int prefixlen,
-                                          const struct in6_addr *gwaddr, int ifindex)
+                                          const struct in6_addr *gwaddr,
+                                          struct net_device *dev)
 {
+       u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO;
+       int ifindex = dev->ifindex;
        struct fib6_node *fn;
        struct rt6_info *rt = NULL;
        struct fib6_table *table;
 
-       table = fib6_get_table(net, RT6_TABLE_INFO);
+       table = fib6_get_table(net, tb_id);
        if (!table)
                return NULL;
 
@@ -2357,12 +2364,13 @@ out:
 
 static struct rt6_info *rt6_add_route_info(struct net *net,
                                           const struct in6_addr *prefix, int prefixlen,
-                                          const struct in6_addr *gwaddr, int ifindex,
+                                          const struct in6_addr *gwaddr,
+                                          struct net_device *dev,
                                           unsigned int pref)
 {
        struct fib6_config cfg = {
                .fc_metric      = IP6_RT_PRIO_USER,
-               .fc_ifindex     = ifindex,
+               .fc_ifindex     = dev->ifindex,
                .fc_dst_len     = prefixlen,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
                                  RTF_UP | RTF_PREF(pref),
@@ -2371,7 +2379,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
                .fc_nlinfo.nl_net = net,
        };
 
-       cfg.fc_table = l3mdev_fib_table_by_index(net, ifindex) ? : RT6_TABLE_INFO;
+       cfg.fc_table = l3mdev_fib_table(dev) ? : RT6_TABLE_INFO,
        cfg.fc_dst = *prefix;
        cfg.fc_gateway = *gwaddr;
 
@@ -2381,16 +2389,17 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
 
        ip6_route_add(&cfg);
 
-       return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
+       return rt6_get_route_info(net, prefix, prefixlen, gwaddr, dev);
 }
 #endif
 
 struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev)
 {
+       u32 tb_id = l3mdev_fib_table(dev) ? : RT6_TABLE_DFLT;
        struct rt6_info *rt;
        struct fib6_table *table;
 
-       table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
+       table = fib6_get_table(dev_net(dev), tb_id);
        if (!table)
                return NULL;
 
@@ -2424,20 +2433,20 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
 
        cfg.fc_gateway = *gwaddr;
 
-       ip6_route_add(&cfg);
+       if (!ip6_route_add(&cfg)) {
+               struct fib6_table *table;
+
+               table = fib6_get_table(dev_net(dev), cfg.fc_table);
+               if (table)
+                       table->flags |= RT6_TABLE_HAS_DFLT_ROUTER;
+       }
 
        return rt6_get_dflt_router(gwaddr, dev);
 }
 
-void rt6_purge_dflt_routers(struct net *net)
+static void __rt6_purge_dflt_routers(struct fib6_table *table)
 {
        struct rt6_info *rt;
-       struct fib6_table *table;
-
-       /* NOTE: Keep consistent with rt6_get_dflt_router */
-       table = fib6_get_table(net, RT6_TABLE_DFLT);
-       if (!table)
-               return;
 
 restart:
        read_lock_bh(&table->tb6_lock);
@@ -2451,6 +2460,27 @@ restart:
                }
        }
        read_unlock_bh(&table->tb6_lock);
+
+       table->flags &= ~RT6_TABLE_HAS_DFLT_ROUTER;
+}
+
+void rt6_purge_dflt_routers(struct net *net)
+{
+       struct fib6_table *table;
+       struct hlist_head *head;
+       unsigned int h;
+
+       rcu_read_lock();
+
+       for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
+               head = &net->ipv6.fib_table_hash[h];
+               hlist_for_each_entry_rcu(table, head, tb6_hlist) {
+                       if (table->flags & RT6_TABLE_HAS_DFLT_ROUTER)
+                               __rt6_purge_dflt_routers(table);
+               }
+       }
+
+       rcu_read_unlock();
 }
 
 static void rtmsg_to_fib6_config(struct net *net,
index 9aa7c1c..b2ef061 100644 (file)
@@ -427,7 +427,8 @@ try_again:
 
        if (is_udp4) {
                if (inet->cmsg_flags)
-                       ip_cmsg_recv(msg, skb);
+                       ip_cmsg_recv_offset(msg, skb,
+                                           sizeof(struct udphdr), off);
        } else {
                if (np->rxopt.all)
                        ip6_datagram_recv_specific_ctl(sk, msg, skb);
index 42de4cc..fce25af 100644 (file)
@@ -338,7 +338,7 @@ static int l2tp_ip_disconnect(struct sock *sk, int flags)
        if (sock_flag(sk, SOCK_ZAPPED))
                return 0;
 
-       return udp_disconnect(sk, flags);
+       return __udp_disconnect(sk, flags);
 }
 
 static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr,
index ea2ae66..ad3468c 100644 (file)
@@ -410,7 +410,7 @@ static int l2tp_ip6_disconnect(struct sock *sk, int flags)
        if (sock_flag(sk, SOCK_ZAPPED))
                return 0;
 
-       return udp_disconnect(sk, flags);
+       return __udp_disconnect(sk, flags);
 }
 
 static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr,
index 7663c28..a4e0d59 100644 (file)
 #include "key.h"
 #include "aes_ccm.h"
 
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-                              u8 *data, size_t data_len, u8 *mic,
-                              size_t mic_len)
+int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+                             u8 *data, size_t data_len, u8 *mic,
+                             size_t mic_len)
 {
        struct scatterlist sg[3];
+       struct aead_request *aead_req;
+       int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+       u8 *__aad;
 
-       char aead_req_data[sizeof(struct aead_request) +
-                          crypto_aead_reqsize(tfm)]
-               __aligned(__alignof__(struct aead_request));
-       struct aead_request *aead_req = (void *) aead_req_data;
+       aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
+       if (!aead_req)
+               return -ENOMEM;
 
-       memset(aead_req, 0, sizeof(aead_req_data));
+       __aad = (u8 *)aead_req + reqsize;
+       memcpy(__aad, aad, CCM_AAD_LEN);
 
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, mic_len);
 
@@ -41,6 +44,9 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
        aead_request_set_ad(aead_req, sg[0].length);
 
        crypto_aead_encrypt(aead_req);
+       kzfree(aead_req);
+
+       return 0;
 }
 
 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
@@ -48,18 +54,23 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
                              size_t mic_len)
 {
        struct scatterlist sg[3];
-       char aead_req_data[sizeof(struct aead_request) +
-                          crypto_aead_reqsize(tfm)]
-               __aligned(__alignof__(struct aead_request));
-       struct aead_request *aead_req = (void *) aead_req_data;
+       struct aead_request *aead_req;
+       int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+       u8 *__aad;
+       int err;
 
        if (data_len == 0)
                return -EINVAL;
 
-       memset(aead_req, 0, sizeof(aead_req_data));
+       aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC);
+       if (!aead_req)
+               return -ENOMEM;
+
+       __aad = (u8 *)aead_req + reqsize;
+       memcpy(__aad, aad, CCM_AAD_LEN);
 
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, mic_len);
 
@@ -67,7 +78,10 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
        aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0);
        aead_request_set_ad(aead_req, sg[0].length);
 
-       return crypto_aead_decrypt(aead_req);
+       err = crypto_aead_decrypt(aead_req);
+       kzfree(aead_req);
+
+       return err;
 }
 
 struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
index 6a73d1e..fcd3254 100644 (file)
 
 #include <linux/crypto.h>
 
+#define CCM_AAD_LEN    32
+
 struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
                                                    size_t key_len,
                                                    size_t mic_len);
-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-                              u8 *data, size_t data_len, u8 *mic,
-                              size_t mic_len);
+int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+                             u8 *data, size_t data_len, u8 *mic,
+                             size_t mic_len);
 int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
                              u8 *data, size_t data_len, u8 *mic,
                              size_t mic_len);
index 3afe361..8a4397c 100644 (file)
 #include "key.h"
 #include "aes_gcm.h"
 
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-                              u8 *data, size_t data_len, u8 *mic)
+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+                             u8 *data, size_t data_len, u8 *mic)
 {
        struct scatterlist sg[3];
+       struct aead_request *aead_req;
+       int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+       u8 *__aad;
 
-       char aead_req_data[sizeof(struct aead_request) +
-                          crypto_aead_reqsize(tfm)]
-               __aligned(__alignof__(struct aead_request));
-       struct aead_request *aead_req = (void *)aead_req_data;
+       aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+       if (!aead_req)
+               return -ENOMEM;
 
-       memset(aead_req, 0, sizeof(aead_req_data));
+       __aad = (u8 *)aead_req + reqsize;
+       memcpy(__aad, aad, GCM_AAD_LEN);
 
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
@@ -37,24 +40,31 @@ void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
        aead_request_set_ad(aead_req, sg[0].length);
 
        crypto_aead_encrypt(aead_req);
+       kzfree(aead_req);
+       return 0;
 }
 
 int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
                              u8 *data, size_t data_len, u8 *mic)
 {
        struct scatterlist sg[3];
-       char aead_req_data[sizeof(struct aead_request) +
-                          crypto_aead_reqsize(tfm)]
-               __aligned(__alignof__(struct aead_request));
-       struct aead_request *aead_req = (void *)aead_req_data;
+       struct aead_request *aead_req;
+       int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+       u8 *__aad;
+       int err;
 
        if (data_len == 0)
                return -EINVAL;
 
-       memset(aead_req, 0, sizeof(aead_req_data));
+       aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
+       if (!aead_req)
+               return -ENOMEM;
+
+       __aad = (u8 *)aead_req + reqsize;
+       memcpy(__aad, aad, GCM_AAD_LEN);
 
        sg_init_table(sg, 3);
-       sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad));
+       sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad));
        sg_set_buf(&sg[1], data, data_len);
        sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN);
 
@@ -63,7 +73,10 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
                               data_len + IEEE80211_GCMP_MIC_LEN, j_0);
        aead_request_set_ad(aead_req, sg[0].length);
 
-       return crypto_aead_decrypt(aead_req);
+       err = crypto_aead_decrypt(aead_req);
+       kzfree(aead_req);
+
+       return err;
 }
 
 struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
index 1347fda..55aed53 100644 (file)
 
 #include <linux/crypto.h>
 
-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-                              u8 *data, size_t data_len, u8 *mic);
+#define GCM_AAD_LEN    32
+
+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
+                             u8 *data, size_t data_len, u8 *mic);
 int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
                              u8 *data, size_t data_len, u8 *mic);
 struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
index 3ddd927..bd72a86 100644 (file)
 #include "key.h"
 #include "aes_gmac.h"
 
-#define GMAC_MIC_LEN 16
-#define GMAC_NONCE_LEN 12
-#define AAD_LEN 20
-
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
                       const u8 *data, size_t data_len, u8 *mic)
 {
        struct scatterlist sg[4];
-       char aead_req_data[sizeof(struct aead_request) +
-                          crypto_aead_reqsize(tfm)]
-               __aligned(__alignof__(struct aead_request));
-       struct aead_request *aead_req = (void *)aead_req_data;
-       u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
+       u8 *zero, *__aad, iv[AES_BLOCK_SIZE];
+       struct aead_request *aead_req;
+       int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
 
        if (data_len < GMAC_MIC_LEN)
                return -EINVAL;
 
-       memset(aead_req, 0, sizeof(aead_req_data));
+       aead_req = kzalloc(reqsize + GMAC_MIC_LEN + GMAC_AAD_LEN, GFP_ATOMIC);
+       if (!aead_req)
+               return -ENOMEM;
+
+       zero = (u8 *)aead_req + reqsize;
+       __aad = zero + GMAC_MIC_LEN;
+       memcpy(__aad, aad, GMAC_AAD_LEN);
 
-       memset(zero, 0, GMAC_MIC_LEN);
        sg_init_table(sg, 4);
-       sg_set_buf(&sg[0], aad, AAD_LEN);
+       sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN);
        sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
        sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
        sg_set_buf(&sg[3], mic, GMAC_MIC_LEN);
@@ -49,9 +48,10 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
 
        aead_request_set_tfm(aead_req, tfm);
        aead_request_set_crypt(aead_req, sg, sg, 0, iv);
-       aead_request_set_ad(aead_req, AAD_LEN + data_len);
+       aead_request_set_ad(aead_req, GMAC_AAD_LEN + data_len);
 
        crypto_aead_encrypt(aead_req);
+       kzfree(aead_req);
 
        return 0;
 }
index d328204..32e6442 100644 (file)
 
 #include <linux/crypto.h>
 
+#define GMAC_AAD_LEN   20
+#define GMAC_MIC_LEN   16
+#define GMAC_NONCE_LEN 12
+
 struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
                                                 size_t key_len);
 int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
index c3f610b..eede5c6 100644 (file)
@@ -820,7 +820,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                    mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT)
                        break;
                rcu_read_lock();
-               sta = sta_info_get(sdata, mgmt->da);
+               sta = sta_info_get_bss(sdata, mgmt->da);
                rcu_read_unlock();
                if (!sta)
                        return -ENOLINK;
index 6175db3..a47bbc9 100644 (file)
@@ -2298,6 +2298,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        __le16 fc = hdr->frame_control;
        struct sk_buff_head frame_list;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+       struct ethhdr ethhdr;
+       const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
 
        if (unlikely(!ieee80211_is_data(fc)))
                return RX_CONTINUE;
@@ -2308,24 +2310,53 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        if (!(status->rx_flags & IEEE80211_RX_AMSDU))
                return RX_CONTINUE;
 
-       if (ieee80211_has_a4(hdr->frame_control) &&
-           rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-           !rx->sdata->u.vlan.sta)
-               return RX_DROP_UNUSABLE;
+       if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
+               switch (rx->sdata->vif.type) {
+               case NL80211_IFTYPE_AP_VLAN:
+                       if (!rx->sdata->u.vlan.sta)
+                               return RX_DROP_UNUSABLE;
+                       break;
+               case NL80211_IFTYPE_STATION:
+                       if (!rx->sdata->u.mgd.use_4addr)
+                               return RX_DROP_UNUSABLE;
+                       break;
+               default:
+                       return RX_DROP_UNUSABLE;
+               }
+               check_da = NULL;
+               check_sa = NULL;
+       } else switch (rx->sdata->vif.type) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_AP_VLAN:
+                       check_da = NULL;
+                       break;
+               case NL80211_IFTYPE_STATION:
+                       if (!rx->sta ||
+                           !test_sta_flag(rx->sta, WLAN_STA_TDLS_PEER))
+                               check_sa = NULL;
+                       break;
+               case NL80211_IFTYPE_MESH_POINT:
+                       check_sa = NULL;
+                       break;
+               default:
+                       break;
+       }
 
-       if (is_multicast_ether_addr(hdr->addr1) &&
-           ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-             rx->sdata->u.vlan.sta) ||
-            (rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
-             rx->sdata->u.mgd.use_4addr)))
+       if (is_multicast_ether_addr(hdr->addr1))
                return RX_DROP_UNUSABLE;
 
        skb->dev = dev;
        __skb_queue_head_init(&frame_list);
 
+       if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
+                                         rx->sdata->vif.addr,
+                                         rx->sdata->vif.type))
+               return RX_DROP_UNUSABLE;
+
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
                                 rx->sdata->vif.type,
-                                rx->local->hw.extra_tx_headroom, true);
+                                rx->local->hw.extra_tx_headroom,
+                                check_da, check_sa);
 
        while (!skb_queue_empty(&frame_list)) {
                rx->skb = __skb_dequeue(&frame_list);
index b48c1e1..42ce9bd 100644 (file)
@@ -405,7 +405,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
        u8 *pos;
        u8 pn[6];
        u64 pn64;
-       u8 aad[2 * AES_BLOCK_SIZE];
+       u8 aad[CCM_AAD_LEN];
        u8 b_0[AES_BLOCK_SIZE];
 
        if (info->control.hw_key &&
@@ -461,10 +461,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
 
        pos += IEEE80211_CCMP_HDR_LEN;
        ccmp_special_blocks(skb, pn, b_0, aad);
-       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
-                                 skb_put(skb, mic_len), mic_len);
-
-       return 0;
+       return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+                                        skb_put(skb, mic_len), mic_len);
 }
 
 
@@ -639,7 +637,7 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        u8 *pos;
        u8 pn[6];
        u64 pn64;
-       u8 aad[2 * AES_BLOCK_SIZE];
+       u8 aad[GCM_AAD_LEN];
        u8 j_0[AES_BLOCK_SIZE];
 
        if (info->control.hw_key &&
@@ -696,10 +694,8 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
        pos += IEEE80211_GCMP_HDR_LEN;
        gcmp_special_blocks(skb, pn, j_0, aad);
-       ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
-                                 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
-
-       return 0;
+       return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
+                                        skb_put(skb, IEEE80211_GCMP_MIC_LEN));
 }
 
 ieee80211_tx_result
@@ -1123,9 +1119,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
        struct ieee80211_key *key = tx->key;
        struct ieee80211_mmie_16 *mmie;
        struct ieee80211_hdr *hdr;
-       u8 aad[20];
+       u8 aad[GMAC_AAD_LEN];
        u64 pn64;
-       u8 nonce[12];
+       u8 nonce[GMAC_NONCE_LEN];
 
        if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
                return TX_DROP;
@@ -1171,7 +1167,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_key *key = rx->key;
        struct ieee80211_mmie_16 *mmie;
-       u8 aad[20], mic[16], ipn[6], nonce[12];
+       u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
        if (!ieee80211_is_mgmt(hdr->frame_control))
index 13290a7..1308a56 100644 (file)
@@ -246,6 +246,7 @@ enum {
        ncsi_dev_state_config_gls,
        ncsi_dev_state_config_done,
        ncsi_dev_state_suspend_select   = 0x0401,
+       ncsi_dev_state_suspend_gls,
        ncsi_dev_state_suspend_dcnt,
        ncsi_dev_state_suspend_dc,
        ncsi_dev_state_suspend_deselect,
@@ -264,6 +265,7 @@ struct ncsi_dev_priv {
 #endif
        unsigned int        package_num;     /* Number of packages         */
        struct list_head    packages;        /* List of packages           */
+       struct ncsi_channel *hot_channel;    /* Channel was ever active    */
        struct ncsi_request requests[256];   /* Request table              */
        unsigned int        request_id;      /* Last used request ID       */
 #define NCSI_REQ_START_IDX     1
index b41a661..6898e72 100644 (file)
@@ -141,23 +141,35 @@ static int ncsi_aen_handler_hncdsc(struct ncsi_dev_priv *ndp,
                return -ENODEV;
 
        /* If the channel is active one, we need reconfigure it */
+       spin_lock_irqsave(&nc->lock, flags);
        ncm = &nc->modes[NCSI_MODE_LINK];
        hncdsc = (struct ncsi_aen_hncdsc_pkt *)h;
        ncm->data[3] = ntohl(hncdsc->status);
        if (!list_empty(&nc->link) ||
-           nc->state != NCSI_CHANNEL_ACTIVE ||
-           (ncm->data[3] & 0x1))
+           nc->state != NCSI_CHANNEL_ACTIVE) {
+               spin_unlock_irqrestore(&nc->lock, flags);
                return 0;
+       }
 
-       if (ndp->flags & NCSI_DEV_HWA)
+       spin_unlock_irqrestore(&nc->lock, flags);
+       if (!(ndp->flags & NCSI_DEV_HWA) && !(ncm->data[3] & 0x1))
                ndp->flags |= NCSI_DEV_RESHUFFLE;
 
        /* If this channel is the active one and the link doesn't
         * work, we have to choose another channel to be active one.
         * The logic here is exactly similar to what we do when link
         * is down on the active channel.
+        *
+        * On the other hand, we need configure it when host driver
+        * state on the active channel becomes ready.
         */
        ncsi_stop_channel_monitor(nc);
+
+       spin_lock_irqsave(&nc->lock, flags);
+       nc->state = (ncm->data[3] & 0x1) ? NCSI_CHANNEL_INACTIVE :
+                                          NCSI_CHANNEL_ACTIVE;
+       spin_unlock_irqrestore(&nc->lock, flags);
+
        spin_lock_irqsave(&ndp->lock, flags);
        list_add_tail_rcu(&nc->link, &ndp->channel_queue);
        spin_unlock_irqrestore(&ndp->lock, flags);
index 5e509e5..a3bd5fa 100644 (file)
@@ -540,42 +540,86 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
                nd->state = ncsi_dev_state_suspend_select;
                /* Fall through */
        case ncsi_dev_state_suspend_select:
-       case ncsi_dev_state_suspend_dcnt:
-       case ncsi_dev_state_suspend_dc:
-       case ncsi_dev_state_suspend_deselect:
                ndp->pending_req_num = 1;
 
-               np = ndp->active_package;
-               nc = ndp->active_channel;
+               nca.type = NCSI_PKT_CMD_SP;
                nca.package = np->id;
-               if (nd->state == ncsi_dev_state_suspend_select) {
-                       nca.type = NCSI_PKT_CMD_SP;
-                       nca.channel = NCSI_RESERVED_CHANNEL;
-                       if (ndp->flags & NCSI_DEV_HWA)
-                               nca.bytes[0] = 0;
-                       else
-                               nca.bytes[0] = 1;
+               nca.channel = NCSI_RESERVED_CHANNEL;
+               if (ndp->flags & NCSI_DEV_HWA)
+                       nca.bytes[0] = 0;
+               else
+                       nca.bytes[0] = 1;
+
+               /* To retrieve the last link states of channels in current
+                * package when current active channel needs fail over to
+                * another one. It means we will possibly select another
+                * channel as next active one. The link states of channels
+                * are most important factor of the selection. So we need
+                * accurate link states. Unfortunately, the link states on
+                * inactive channels can't be updated with LSC AEN in time.
+                */
+               if (ndp->flags & NCSI_DEV_RESHUFFLE)
+                       nd->state = ncsi_dev_state_suspend_gls;
+               else
                        nd->state = ncsi_dev_state_suspend_dcnt;
-               } else if (nd->state == ncsi_dev_state_suspend_dcnt) {
-                       nca.type = NCSI_PKT_CMD_DCNT;
-                       nca.channel = nc->id;
-                       nd->state = ncsi_dev_state_suspend_dc;
-               } else if (nd->state == ncsi_dev_state_suspend_dc) {
-                       nca.type = NCSI_PKT_CMD_DC;
+               ret = ncsi_xmit_cmd(&nca);
+               if (ret)
+                       goto error;
+
+               break;
+       case ncsi_dev_state_suspend_gls:
+               ndp->pending_req_num = np->channel_num;
+
+               nca.type = NCSI_PKT_CMD_GLS;
+               nca.package = np->id;
+
+               nd->state = ncsi_dev_state_suspend_dcnt;
+               NCSI_FOR_EACH_CHANNEL(np, nc) {
                        nca.channel = nc->id;
-                       nca.bytes[0] = 1;
-                       nd->state = ncsi_dev_state_suspend_deselect;
-               } else if (nd->state == ncsi_dev_state_suspend_deselect) {
-                       nca.type = NCSI_PKT_CMD_DP;
-                       nca.channel = NCSI_RESERVED_CHANNEL;
-                       nd->state = ncsi_dev_state_suspend_done;
+                       ret = ncsi_xmit_cmd(&nca);
+                       if (ret)
+                               goto error;
                }
 
+               break;
+       case ncsi_dev_state_suspend_dcnt:
+               ndp->pending_req_num = 1;
+
+               nca.type = NCSI_PKT_CMD_DCNT;
+               nca.package = np->id;
+               nca.channel = nc->id;
+
+               nd->state = ncsi_dev_state_suspend_dc;
                ret = ncsi_xmit_cmd(&nca);
-               if (ret) {
-                       nd->state = ncsi_dev_state_functional;
-                       return;
-               }
+               if (ret)
+                       goto error;
+
+               break;
+       case ncsi_dev_state_suspend_dc:
+               ndp->pending_req_num = 1;
+
+               nca.type = NCSI_PKT_CMD_DC;
+               nca.package = np->id;
+               nca.channel = nc->id;
+               nca.bytes[0] = 1;
+
+               nd->state = ncsi_dev_state_suspend_deselect;
+               ret = ncsi_xmit_cmd(&nca);
+               if (ret)
+                       goto error;
+
+               break;
+       case ncsi_dev_state_suspend_deselect:
+               ndp->pending_req_num = 1;
+
+               nca.type = NCSI_PKT_CMD_DP;
+               nca.package = np->id;
+               nca.channel = NCSI_RESERVED_CHANNEL;
+
+               nd->state = ncsi_dev_state_suspend_done;
+               ret = ncsi_xmit_cmd(&nca);
+               if (ret)
+                       goto error;
 
                break;
        case ncsi_dev_state_suspend_done:
@@ -589,6 +633,10 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
                netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n",
                            nd->state);
        }
+
+       return;
+error:
+       nd->state = ncsi_dev_state_functional;
 }
 
 static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
@@ -597,6 +645,7 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
        struct net_device *dev = nd->dev;
        struct ncsi_package *np = ndp->active_package;
        struct ncsi_channel *nc = ndp->active_channel;
+       struct ncsi_channel *hot_nc = NULL;
        struct ncsi_cmd_arg nca;
        unsigned char index;
        unsigned long flags;
@@ -702,12 +751,20 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
                break;
        case ncsi_dev_state_config_done:
                spin_lock_irqsave(&nc->lock, flags);
-               if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1)
+               if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
+                       hot_nc = nc;
                        nc->state = NCSI_CHANNEL_ACTIVE;
-               else
+               } else {
+                       hot_nc = NULL;
                        nc->state = NCSI_CHANNEL_INACTIVE;
+               }
                spin_unlock_irqrestore(&nc->lock, flags);
 
+               /* Update the hot channel */
+               spin_lock_irqsave(&ndp->lock, flags);
+               ndp->hot_channel = hot_nc;
+               spin_unlock_irqrestore(&ndp->lock, flags);
+
                ncsi_start_channel_monitor(nc);
                ncsi_process_next_channel(ndp);
                break;
@@ -725,10 +782,14 @@ error:
 static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
 {
        struct ncsi_package *np;
-       struct ncsi_channel *nc, *found;
+       struct ncsi_channel *nc, *found, *hot_nc;
        struct ncsi_channel_mode *ncm;
        unsigned long flags;
 
+       spin_lock_irqsave(&ndp->lock, flags);
+       hot_nc = ndp->hot_channel;
+       spin_unlock_irqrestore(&ndp->lock, flags);
+
        /* The search is done once an inactive channel with up
         * link is found.
         */
@@ -746,6 +807,9 @@ static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
                        if (!found)
                                found = nc;
 
+                       if (nc == hot_nc)
+                               found = nc;
+
                        ncm = &nc->modes[NCSI_MODE_LINK];
                        if (ncm->data[2] & 0x1) {
                                spin_unlock_irqrestore(&nc->lock, flags);
index fcb5d1d..004af03 100644 (file)
@@ -361,16 +361,9 @@ next_hook:
                if (ret == 0)
                        ret = -EPERM;
        } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
-               int err;
-
-               RCU_INIT_POINTER(state->hook_entries, entry);
-               err = nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
-               if (err < 0) {
-                       if (err == -ESRCH &&
-                          (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
-                               goto next_hook;
-                       kfree_skb(skb);
-               }
+               ret = nf_queue(skb, state, &entry, verdict);
+               if (ret == 1 && entry)
+                       goto next_hook;
        }
        return ret;
 }
index ba6a1d4..df2f5a3 100644 (file)
@@ -983,7 +983,7 @@ static void gc_worker(struct work_struct *work)
                return;
 
        ratio = scanned ? expired_count * 100 / scanned : 0;
-       if (ratio >= 90)
+       if (ratio >= 90 || expired_count == GC_MAX_EVICTS)
                next_run = 0;
 
        gc_work->last_bucket = i;
index e0adb59..9fdb655 100644 (file)
@@ -18,7 +18,7 @@ unsigned int nf_iterate(struct sk_buff *skb, struct nf_hook_state *state,
 
 /* nf_queue.c */
 int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
-            unsigned int queuenum);
+            struct nf_hook_entry **entryp, unsigned int verdict);
 void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry);
 int __init netfilter_queue_init(void);
 
index 96964a0..8f08d75 100644 (file)
@@ -107,13 +107,8 @@ void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry)
        rcu_read_unlock();
 }
 
-/*
- * Any packet that leaves via this function must come back
- * through nf_reinject().
- */
-int nf_queue(struct sk_buff *skb,
-            struct nf_hook_state *state,
-            unsigned int queuenum)
+static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
+                     unsigned int queuenum)
 {
        int status = -ENOENT;
        struct nf_queue_entry *entry = NULL;
@@ -161,6 +156,27 @@ err:
        return status;
 }
 
+/* Packets leaving via this function must come back through nf_reinject(). */
+int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
+            struct nf_hook_entry **entryp, unsigned int verdict)
+{
+       struct nf_hook_entry *entry = *entryp;
+       int ret;
+
+       RCU_INIT_POINTER(state->hook_entries, entry);
+       ret = __nf_queue(skb, state, verdict >> NF_VERDICT_QBITS);
+       if (ret < 0) {
+               if (ret == -ESRCH &&
+                   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) {
+                       *entryp = rcu_dereference(entry->next);
+                       return 1;
+               }
+               kfree_skb(skb);
+       }
+
+       return 0;
+}
+
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 {
        struct nf_hook_entry *hook_entry;
@@ -187,26 +203,26 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
        entry->state.thresh = INT_MIN;
 
        if (verdict == NF_ACCEPT) {
-       next_hook:
-               verdict = nf_iterate(skb, &entry->state, &hook_entry);
+               hook_entry = rcu_dereference(hook_entry->next);
+               if (hook_entry)
+next_hook:
+                       verdict = nf_iterate(skb, &entry->state, &hook_entry);
        }
 
        switch (verdict & NF_VERDICT_MASK) {
        case NF_ACCEPT:
        case NF_STOP:
+okfn:
                local_bh_disable();
                entry->state.okfn(entry->state.net, entry->state.sk, skb);
                local_bh_enable();
                break;
        case NF_QUEUE:
-               RCU_INIT_POINTER(entry->state.hook_entries, hook_entry);
-               err = nf_queue(skb, &entry->state,
-                              verdict >> NF_VERDICT_QBITS);
-               if (err < 0) {
-                       if (err == -ESRCH &&
-                          (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+               err = nf_queue(skb, &entry->state, &hook_entry, verdict);
+               if (err == 1) {
+                       if (hook_entry)
                                goto next_hook;
-                       kfree_skb(skb);
+                       goto okfn;
                }
                break;
        case NF_STOLEN:
index b70d3ea..24db222 100644 (file)
@@ -4423,7 +4423,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
  */
 unsigned int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
 {
-       int val;
+       u32 val;
 
        val = ntohl(nla_get_be32(attr));
        if (val > max)
index e3b83c3..517f087 100644 (file)
@@ -158,7 +158,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
        if (tb[NFTA_DYNSET_TIMEOUT] != NULL) {
                if (!(set->flags & NFT_SET_TIMEOUT))
                        return -EINVAL;
-               timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT]));
+               timeout = msecs_to_jiffies(be64_to_cpu(nla_get_be64(
+                                               tb[NFTA_DYNSET_TIMEOUT])));
        }
 
        priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
@@ -246,7 +247,8 @@ static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr)
                goto nla_put_failure;
        if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name))
                goto nla_put_failure;
-       if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout),
+       if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT,
+                        cpu_to_be64(jiffies_to_msecs(priv->timeout)),
                         NFTA_DYNSET_PAD))
                goto nla_put_failure;
        if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr))
index a84cf3d..47beb3a 100644 (file)
@@ -59,7 +59,8 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
                           const struct nlattr * const tb[])
 {
        struct nft_exthdr *priv = nft_expr_priv(expr);
-       u32 offset, len, err;
+       u32 offset, len;
+       int err;
 
        if (tb[NFTA_EXTHDR_DREG] == NULL ||
            tb[NFTA_EXTHDR_TYPE] == NULL ||
index 09473b4..baf694d 100644 (file)
@@ -44,6 +44,7 @@ static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
        [NFTA_HASH_LEN]         = { .type = NLA_U32 },
        [NFTA_HASH_MODULUS]     = { .type = NLA_U32 },
        [NFTA_HASH_SEED]        = { .type = NLA_U32 },
+       [NFTA_HASH_OFFSET]      = { .type = NLA_U32 },
 };
 
 static int nft_hash_init(const struct nft_ctx *ctx,
index c6d5358..fbc8800 100644 (file)
@@ -28,22 +28,20 @@ static void nft_range_eval(const struct nft_expr *expr,
                         const struct nft_pktinfo *pkt)
 {
        const struct nft_range_expr *priv = nft_expr_priv(expr);
-       bool mismatch;
        int d1, d2;
 
        d1 = memcmp(&regs->data[priv->sreg], &priv->data_from, priv->len);
        d2 = memcmp(&regs->data[priv->sreg], &priv->data_to, priv->len);
        switch (priv->op) {
        case NFT_RANGE_EQ:
-               mismatch = (d1 < 0 || d2 > 0);
+               if (d1 < 0 || d2 > 0)
+                       regs->verdict.code = NFT_BREAK;
                break;
        case NFT_RANGE_NEQ:
-               mismatch = (d1 >= 0 && d2 <= 0);
+               if (d1 >= 0 && d2 <= 0)
+                       regs->verdict.code = NFT_BREAK;
                break;
        }
-
-       if (mismatch)
-               regs->verdict.code = NFT_BREAK;
 }
 
 static const struct nla_policy nft_range_policy[NFTA_RANGE_MAX + 1] = {
@@ -59,6 +57,7 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        struct nft_range_expr *priv = nft_expr_priv(expr);
        struct nft_data_desc desc_from, desc_to;
        int err;
+       u32 op;
 
        err = nft_data_init(NULL, &priv->data_from, sizeof(priv->data_from),
                            &desc_from, tb[NFTA_RANGE_FROM_DATA]);
@@ -80,7 +79,20 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        if (err < 0)
                goto err2;
 
-       priv->op  = ntohl(nla_get_be32(tb[NFTA_RANGE_OP]));
+       err = nft_parse_u32_check(tb[NFTA_RANGE_OP], U8_MAX, &op);
+       if (err < 0)
+               goto err2;
+
+       switch (op) {
+       case NFT_RANGE_EQ:
+       case NFT_RANGE_NEQ:
+               break;
+       default:
+               err = -EINVAL;
+               goto err2;
+       }
+
+       priv->op  = op;
        priv->len = desc_from.len;
        return 0;
 err2:
index e0aa7c1..fc49774 100644 (file)
@@ -1513,7 +1513,7 @@ xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn)
        if (!num_hooks)
                return ERR_PTR(-EINVAL);
 
-       ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
+       ops = kcalloc(num_hooks, sizeof(*ops), GFP_KERNEL);
        if (ops == NULL)
                return ERR_PTR(-ENOMEM);
 
index 018eed7..8668a5c 100644 (file)
@@ -32,6 +32,7 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
        li.u.ulog.copy_len   = info->len;
        li.u.ulog.group      = info->group;
        li.u.ulog.qthreshold = info->threshold;
+       li.u.ulog.flags      = 0;
 
        if (info->flags & XT_NFLOG_F_COPY_LEN)
                li.u.ulog.flags |= NF_LOG_F_COPY_LEN;
index 2fab0c6..b89b688 100644 (file)
@@ -431,7 +431,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
    CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
 */
 #define MAX_CPJ_v1 (0xFFFFFFFF / (HZ*60*60*24))
-#define MAX_CPJ (0xFFFFFFFFFFFFFFFF / (HZ*60*60*24))
+#define MAX_CPJ (0xFFFFFFFFFFFFFFFFULL / (HZ*60*60*24))
 
 /* Repeated shift and or gives us all 1s, final shift and add 1 gives
  * us the power of 2 below the theoretical max, so GCC simply does a
@@ -473,7 +473,7 @@ static u64 user2credits(u64 user, int revision)
                return div64_u64(user * HZ * CREDITS_PER_JIFFY_v1,
                                 XT_HASHLIMIT_SCALE);
        } else {
-               if (user > 0xFFFFFFFFFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
+               if (user > 0xFFFFFFFFFFFFFFFFULL / (HZ*CREDITS_PER_JIFFY))
                        return div64_u64(user, XT_HASHLIMIT_SCALE_v2)
                                * HZ * CREDITS_PER_JIFFY;
 
index 89d5310..000e703 100644 (file)
@@ -26,6 +26,8 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Fan Du <fan.du@windriver.com>");
 MODULE_DESCRIPTION("Xtables: IPv4/6 IPsec-IPComp SPI match");
+MODULE_ALIAS("ipt_ipcomp");
+MODULE_ALIAS("ip6t_ipcomp");
 
 /* Returns 1 if the spi is matched by the range, 0 otherwise */
 static inline bool
index 11db0d6..d2238b2 100644 (file)
@@ -250,7 +250,7 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po);
 static int packet_direct_xmit(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
-       netdev_features_t features;
+       struct sk_buff *orig_skb = skb;
        struct netdev_queue *txq;
        int ret = NETDEV_TX_BUSY;
 
@@ -258,9 +258,8 @@ static int packet_direct_xmit(struct sk_buff *skb)
                     !netif_carrier_ok(dev)))
                goto drop;
 
-       features = netif_skb_features(skb);
-       if (skb_needs_linearize(skb, features) &&
-           __skb_linearize(skb))
+       skb = validate_xmit_skb_list(skb, dev);
+       if (skb != orig_skb)
                goto drop;
 
        txq = skb_get_tx_queue(dev, skb);
@@ -280,7 +279,7 @@ static int packet_direct_xmit(struct sk_buff *skb)
        return ret;
 drop:
        atomic_long_inc(&dev->tx_dropped);
-       kfree_skb(skb);
+       kfree_skb_list(skb);
        return NET_XMIT_DROP;
 }
 
index 0e72bec..56c7d27 100644 (file)
@@ -13,5 +13,5 @@ obj-$(CONFIG_RDS_TCP) += rds_tcp.o
 rds_tcp-y :=           tcp.o tcp_connect.o tcp_listen.o tcp_recv.o \
                        tcp_send.o tcp_stats.o
 
-ccflags-$(CONFIG_RDS_DEBUG)    :=      -DDEBUG
+ccflags-$(CONFIG_RDS_DEBUG)    :=      -DRDS_DEBUG
 
index fd0bccb..67ba67c 100644 (file)
@@ -33,7 +33,7 @@
 #define KERNEL_HAS_ATOMIC64
 #endif
 
-#ifdef DEBUG
+#ifdef RDS_DEBUG
 #define rdsdebug(fmt, args...) pr_debug("%s(): " fmt, __func__ , ##args)
 #else
 /* sigh, pr_debug() causes unused variable warnings */
index 4353a29..1ed18d8 100644 (file)
@@ -276,7 +276,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
                goto error;
 
        trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage),
-                        here, ERR_PTR(ret));
+                        here, NULL);
 
        spin_lock_bh(&call->conn->params.peer->lock);
        hlist_add_head(&call->error_link,
index 941b724..862eea6 100644 (file)
@@ -193,8 +193,8 @@ static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer)
                fl6->fl6_dport = htons(7001);
                fl6->fl6_sport = htons(7000);
                dst = ip6_route_output(&init_net, NULL, fl6);
-               if (IS_ERR(dst)) {
-                       _leave(" [route err %ld]", PTR_ERR(dst));
+               if (dst->error) {
+                       _leave(" [route err %d]", dst->error);
                        return;
                }
                break;
index a512b18..f893d18 100644 (file)
@@ -1028,8 +1028,7 @@ static struct nlattr *find_dump_kind(const struct nlmsghdr *n)
 
        if (tb[1] == NULL)
                return NULL;
-       if (nla_parse(tb2, TCA_ACT_MAX, nla_data(tb[1]),
-                     nla_len(tb[1]), NULL) < 0)
+       if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL) < 0)
                return NULL;
        kind = tb2[TCA_ACT_KIND];
 
index 667dc38..6b07fba 100644 (file)
@@ -207,8 +207,11 @@ out:
 static void tcf_stats_update(struct tc_action *a, u64 bytes, u32 packets,
                             u64 lastuse)
 {
-       tcf_lastuse_update(&a->tcfa_tm);
+       struct tcf_mirred *m = to_mirred(a);
+       struct tcf_t *tm = &m->tcf_tm;
+
        _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets);
+       tm->lastuse = lastuse;
 }
 
 static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind,
index 2ee29a3..2b2a797 100644 (file)
@@ -345,7 +345,8 @@ replay:
                        if (err == 0) {
                                struct tcf_proto *next = rtnl_dereference(tp->next);
 
-                               tfilter_notify(net, skb, n, tp, fh,
+                               tfilter_notify(net, skb, n, tp,
+                                              t->tcm_handle,
                                               RTM_DELTFILTER, false);
                                if (tcf_destroy(tp, false))
                                        RCU_INIT_POINTER(*back, next);
index 2a5c189..6cb0df8 100644 (file)
@@ -418,6 +418,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
        __u8 has_data = 0;
        int gso = 0;
        int pktcount = 0;
+       int auth_len = 0;
        struct dst_entry *dst;
        unsigned char *auth = NULL;     /* pointer to auth in skb data */
 
@@ -510,7 +511,12 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                        list_for_each_entry(chunk, &packet->chunk_list, list) {
                                int padded = SCTP_PAD4(chunk->skb->len);
 
-                               if (pkt_size + padded > tp->pathmtu)
+                               if (chunk == packet->auth)
+                                       auth_len = padded;
+                               else if (auth_len + padded + packet->overhead >
+                                        tp->pathmtu)
+                                       goto nomem;
+                               else if (pkt_size + padded > tp->pathmtu)
                                        break;
                                pkt_size += padded;
                        }
index 026e3bc..8ec20a6 100644 (file)
@@ -3422,6 +3422,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net,
                        return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
                                                  commands);
 
+               /* Report violation if chunk len overflows */
+               ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
+               if (ch_end > skb_tail_pointer(skb))
+                       return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
+                                                 commands);
+
                /* Now that we know we at least have a chunk header,
                 * do things that are type appropriate.
                 */
@@ -3453,12 +3459,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net,
                        }
                }
 
-               /* Report violation if chunk len overflows */
-               ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
-               if (ch_end > skb_tail_pointer(skb))
-                       return sctp_sf_violation_chunklen(net, ep, asoc, type, arg,
-                                                 commands);
-
                ch = (sctp_chunkhdr_t *) ch_end;
        } while (ch_end < skb_tail_pointer(skb));
 
index fb02c70..9fbb6fe 100644 (file)
@@ -4687,7 +4687,7 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
                                  int __user *optlen)
 {
-       if (len <= 0)
+       if (len == 0)
                return -EINVAL;
        if (len > sizeof(struct sctp_event_subscribe))
                len = sizeof(struct sctp_event_subscribe);
@@ -6430,6 +6430,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
        if (get_user(len, optlen))
                return -EFAULT;
 
+       if (len < 0)
+               return -EINVAL;
+
        lock_sock(sk);
 
        switch (optname) {
index 02beb35..3b95fe9 100644 (file)
@@ -771,6 +771,9 @@ int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        u32 mask = BR_LEARNING | BR_LEARNING_SYNC | BR_FLOOD;
        int err;
 
+       if (!netif_is_bridge_port(dev))
+               return -EOPNOTSUPP;
+
        err = switchdev_port_attr_get(dev, &attr);
        if (err && err != -EOPNOTSUPP)
                return err;
@@ -926,6 +929,9 @@ int switchdev_port_bridge_setlink(struct net_device *dev,
        struct nlattr *afspec;
        int err = 0;
 
+       if (!netif_is_bridge_port(dev))
+               return -EOPNOTSUPP;
+
        protinfo = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
                                   IFLA_PROTINFO);
        if (protinfo) {
@@ -959,6 +965,9 @@ int switchdev_port_bridge_dellink(struct net_device *dev,
 {
        struct nlattr *afspec;
 
+       if (!netif_is_bridge_port(dev))
+               return -EOPNOTSUPP;
+
        afspec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg),
                                 IFLA_AF_SPEC);
        if (afspec)
index 753f774..aa1babb 100644 (file)
@@ -247,11 +247,17 @@ int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb)
  *
  * RCU is locked, no other locks set
  */
-void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked)
+void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
+                       struct tipc_msg *hdr)
 {
        struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
+       u16 acked = msg_bcast_ack(hdr);
        struct sk_buff_head xmitq;
 
+       /* Ignore bc acks sent by peer before bcast synch point was received */
+       if (msg_bc_ack_invalid(hdr))
+               return;
+
        __skb_queue_head_init(&xmitq);
 
        tipc_bcast_lock(net);
@@ -279,11 +285,11 @@ int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
        __skb_queue_head_init(&xmitq);
 
        tipc_bcast_lock(net);
-       if (msg_type(hdr) == STATE_MSG) {
+       if (msg_type(hdr) != STATE_MSG) {
+               tipc_link_bc_init_rcv(l, hdr);
+       } else if (!msg_bc_ack_invalid(hdr)) {
                tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq);
                rc = tipc_link_bc_sync_rcv(l, hdr, &xmitq);
-       } else {
-               tipc_link_bc_init_rcv(l, hdr);
        }
        tipc_bcast_unlock(net);
 
index 5ffe344..855d53c 100644 (file)
@@ -55,7 +55,8 @@ void tipc_bcast_dec_bearer_dst_cnt(struct net *net, int bearer_id);
 int  tipc_bcast_get_mtu(struct net *net);
 int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);
 int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb);
-void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked);
+void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l,
+                       struct tipc_msg *hdr);
 int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
                        struct tipc_msg *hdr);
 int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
index b36e16c..1055164 100644 (file)
@@ -1312,6 +1312,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
        msg_set_next_sent(hdr, l->snd_nxt);
        msg_set_ack(hdr, l->rcv_nxt - 1);
        msg_set_bcast_ack(hdr, bcl->rcv_nxt - 1);
+       msg_set_bc_ack_invalid(hdr, !node_up);
        msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);
        msg_set_link_tolerance(hdr, tolerance);
        msg_set_linkprio(hdr, priority);
@@ -1574,6 +1575,7 @@ static void tipc_link_build_bc_init_msg(struct tipc_link *l,
        __skb_queue_head_init(&list);
        if (!tipc_link_build_bc_proto_msg(l->bc_rcvlink, false, 0, &list))
                return;
+       msg_set_bc_ack_invalid(buf_msg(skb_peek(&list)), true);
        tipc_link_xmit(l, &list, xmitq);
 }
 
index c3832cd..50a7398 100644 (file)
@@ -714,6 +714,23 @@ static inline void msg_set_peer_stopping(struct tipc_msg *m, u32 s)
        msg_set_bits(m, 5, 13, 0x1, s);
 }
 
+static inline bool msg_bc_ack_invalid(struct tipc_msg *m)
+{
+       switch (msg_user(m)) {
+       case BCAST_PROTOCOL:
+       case NAME_DISTRIBUTOR:
+       case LINK_PROTOCOL:
+               return msg_bits(m, 5, 14, 0x1);
+       default:
+               return false;
+       }
+}
+
+static inline void msg_set_bc_ack_invalid(struct tipc_msg *m, bool invalid)
+{
+       msg_set_bits(m, 5, 14, 0x1, invalid);
+}
+
 static inline char *msg_media_addr(struct tipc_msg *m)
 {
        return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET];
index a04fe9b..c1cfd92 100644 (file)
@@ -156,6 +156,7 @@ static void named_distribute(struct net *net, struct sk_buff_head *list,
                                pr_warn("Bulk publication failure\n");
                                return;
                        }
+                       msg_set_bc_ack_invalid(buf_msg(skb), true);
                        item = (struct distr_item *)msg_data(buf_msg(skb));
                }
 
index 7ef14e2..9d2f4c2 100644 (file)
@@ -1535,7 +1535,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
        if (unlikely(usr == LINK_PROTOCOL))
                tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);
        else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
-               tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);
+               tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr);
 
        /* Receive packet directly if conditions permit */
        tipc_node_read_lock(n);
index 0082f4b..14b3f00 100644 (file)
@@ -104,13 +104,16 @@ static int wiphy_suspend(struct device *dev)
 
        rtnl_lock();
        if (rdev->wiphy.registered) {
-               if (!rdev->wiphy.wowlan_config)
+               if (!rdev->wiphy.wowlan_config) {
                        cfg80211_leave_all(rdev);
+                       cfg80211_process_rdev_events(rdev);
+               }
                if (rdev->ops->suspend)
                        ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
                if (ret == 1) {
                        /* Driver refuse to configure wowlan */
                        cfg80211_leave_all(rdev);
+                       cfg80211_process_rdev_events(rdev);
                        ret = rdev_suspend(rdev, NULL);
                }
        }
index 8edce22..5ea12af 100644 (file)
@@ -420,8 +420,8 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
 }
 EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
-static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
-                                   const u8 *addr, enum nl80211_iftype iftype)
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+                                 const u8 *addr, enum nl80211_iftype iftype)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct {
@@ -525,13 +525,7 @@ static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
 
        return 0;
 }
-
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
-                          enum nl80211_iftype iftype)
-{
-       return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
-}
-EXPORT_SYMBOL(ieee80211_data_to_8023);
+EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
 
 int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
                             enum nl80211_iftype iftype,
@@ -746,24 +740,18 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
                              const u8 *addr, enum nl80211_iftype iftype,
                              const unsigned int extra_headroom,
-                             bool has_80211_header)
+                             const u8 *check_da, const u8 *check_sa)
 {
        unsigned int hlen = ALIGN(extra_headroom, 4);
        struct sk_buff *frame = NULL;
        u16 ethertype;
        u8 *payload;
-       int offset = 0, remaining, err;
+       int offset = 0, remaining;
        struct ethhdr eth;
        bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
        bool reuse_skb = false;
        bool last = false;
 
-       if (has_80211_header) {
-               err = __ieee80211_data_to_8023(skb, &eth, addr, iftype);
-               if (err)
-                       goto out;
-       }
-
        while (!last) {
                unsigned int subframe_len;
                int len;
@@ -780,8 +768,17 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
                        goto purge;
 
                offset += sizeof(struct ethhdr);
-               /* reuse skb for the last subframe */
                last = remaining <= subframe_len + padding;
+
+               /* FIXME: should we really accept multicast DA? */
+               if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
+                    !ether_addr_equal(check_da, eth.h_dest)) ||
+                   (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
+                       offset += len + padding;
+                       continue;
+               }
+
+               /* reuse skb for the last subframe */
                if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
                        skb_pull(skb, offset);
                        frame = skb;
@@ -819,7 +816,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 
  purge:
        __skb_queue_purge(list);
- out:
        dev_kfree_skb(skb);
 }
 EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
index d175501..6db6b21 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 <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/in.h>
index cf2511c..10af53d 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 <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/in.h>
index edab34d..95c1632 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 <linux/if_ether.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
index fa051b3..274c884 100644 (file)
@@ -1,3 +1,4 @@
+#define KBUILD_MODNAME "foo"
 #include <uapi/linux/bpf.h>
 #include <uapi/linux/if_ether.h>
 #include <uapi/linux/if_packet.h>
index 3303bb8..9c823a6 100644 (file)
@@ -5,6 +5,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 10ff734..1547b36 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/if_ether.h>
 #include <uapi/linux/in6.h>
 #include <uapi/linux/ipv6.h>
index f826e87..d942c7c 100644 (file)
@@ -41,7 +41,7 @@ config BIG_KEYS
        bool "Large payload keys"
        depends on KEYS
        depends on TMPFS
-       select CRYPTO
+       depends on (CRYPTO_ANSI_CPRNG = y || CRYPTO_DRBG = y)
        select CRYPTO_AES
        select CRYPTO_ECB
        select CRYPTO_RNG
index c0b3030..835c1ab 100644 (file)
@@ -9,6 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) "big_key: "fmt
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/file.h>
@@ -341,44 +342,48 @@ error:
  */
 static int __init big_key_init(void)
 {
-       return register_key_type(&key_type_big_key);
-}
-
-/*
- * Initialize big_key crypto and RNG algorithms
- */
-static int __init big_key_crypto_init(void)
-{
-       int ret = -EINVAL;
+       struct crypto_skcipher *cipher;
+       struct crypto_rng *rng;
+       int ret;
 
-       /* init RNG */
-       big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
-       if (IS_ERR(big_key_rng)) {
-               big_key_rng = NULL;
-               return -EFAULT;
+       rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
+       if (IS_ERR(rng)) {
+               pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
+               return PTR_ERR(rng);
        }
 
+       big_key_rng = rng;
+
        /* seed RNG */
-       ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng));
-       if (ret)
-               goto error;
+       ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
+       if (ret) {
+               pr_err("Can't reset rng: %d\n", ret);
+               goto error_rng;
+       }
 
        /* init block cipher */
-       big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name,
-                                                0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(big_key_skcipher)) {
-               big_key_skcipher = NULL;
-               ret = -EFAULT;
-               goto error;
+       cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(cipher)) {
+               ret = PTR_ERR(cipher);
+               pr_err("Can't alloc crypto: %d\n", ret);
+               goto error_rng;
+       }
+
+       big_key_skcipher = cipher;
+
+       ret = register_key_type(&key_type_big_key);
+       if (ret < 0) {
+               pr_err("Can't register type: %d\n", ret);
+               goto error_cipher;
        }
 
        return 0;
 
-error:
+error_cipher:
+       crypto_free_skcipher(big_key_skcipher);
+error_rng:
        crypto_free_rng(big_key_rng);
-       big_key_rng = NULL;
        return ret;
 }
 
-device_initcall(big_key_init);
-late_initcall(big_key_crypto_init);
+late_initcall(big_key_init);
index f0611a6..b9f531c 100644 (file)
@@ -181,7 +181,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
        struct timespec now;
        unsigned long timo;
        key_ref_t key_ref, skey_ref;
-       char xbuf[12];
+       char xbuf[16];
        int rc;
 
        struct keyring_search_context ctx = {
index 0850579..09fd610 100644 (file)
@@ -3557,7 +3557,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
                } else if (!vma->vm_file &&
                           ((vma->vm_start <= vma->vm_mm->start_stack &&
                             vma->vm_end >= vma->vm_mm->start_stack) ||
-                           vma_is_stack_for_task(vma, current))) {
+                           vma_is_stack_for_current(vma))) {
                        rc = current_has_perm(current, PROCESS__EXECSTACK);
                } else if (vma->vm_file && vma->anon_vma) {
                        /*
index ade7c6c..682b73a 100644 (file)
@@ -881,7 +881,7 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
         * the execve().
         */
        if (get_user_pages_remote(current, bprm->mm, pos, 1,
-                               0, 1, &page, NULL) <= 0)
+                               FOLL_FORCE, &page, NULL) <= 0)
                return false;
 #else
        page = bprm->page[pos / PAGE_SIZE];
index dcc1028..37d9cfb 100644 (file)
@@ -448,8 +448,8 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
 
                ktime_get_ts64(&tm);
                tm = timespec64_sub(tm, tmr->last_update);
-               cur_time.tv_nsec = tm.tv_nsec;
-               cur_time.tv_sec = tm.tv_sec;
+               cur_time.tv_nsec += tm.tv_nsec;
+               cur_time.tv_sec += tm.tv_sec;
                snd_seq_sanity_real_time(&cur_time);
        }
        spin_unlock_irqrestore(&tmr->lock, flags);
index d17937b..7e3aa50 100644 (file)
@@ -111,7 +111,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return -EINVAL;
 
        hm = kmalloc(sizeof(*hm), GFP_KERNEL);
-       hr = kmalloc(sizeof(*hr), GFP_KERNEL);
+       hr = kzalloc(sizeof(*hr), GFP_KERNEL);
        if (!hm || !hr) {
                err = -ENOMEM;
                goto out;
index c3469f7..c64d986 100644 (file)
@@ -341,8 +341,7 @@ enum {
 
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
-       (AZX_DCAPS_NO_MSI | /*AZX_DCAPS_ALIGN_BUFSIZE |*/ \
-        AZX_DCAPS_NO_64BIT | AZX_DCAPS_CORBRP_SELF_CLEAR |\
+       (AZX_DCAPS_NO_MSI | AZX_DCAPS_CORBRP_SELF_CLEAR |\
         AZX_DCAPS_SNOOP_TYPE(NVIDIA))
 
 #define AZX_DCAPS_PRESET_CTHDA \
@@ -1716,6 +1715,10 @@ static int azx_first_init(struct azx *chip)
                }
        }
 
+       /* NVidia hardware normally only supports up to 40 bits of DMA */
+       if (chip->pci->vendor == PCI_VENDOR_ID_NVIDIA)
+               dma_bits = 40;
+
        /* disable 64bit DMA address on some devices */
        if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
                dev_dbg(card->dev, "Disabling 64bit DMA\n");
index b58e8c7..2f909dd 100644 (file)
@@ -5811,8 +5811,6 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
 #define ALC295_STANDARD_PINS \
        {0x12, 0xb7a60130}, \
        {0x14, 0x90170110}, \
-       {0x17, 0x21014020}, \
-       {0x18, 0x21a19030}, \
        {0x21, 0x04211020}
 
 #define ALC298_STANDARD_PINS \
@@ -5858,10 +5856,18 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x14, 0x90170110},
                {0x1b, 0x02011020},
                {0x21, 0x0221101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x14, 0x90170110},
+               {0x1b, 0x01011020},
+               {0x21, 0x0221101f}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x14, 0x90170130},
                {0x1b, 0x01014020},
                {0x21, 0x0221103f}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x14, 0x90170130},
+               {0x1b, 0x01011020},
+               {0x21, 0x0221103f}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x14, 0x90170130},
                {0x1b, 0x02011020},
@@ -6039,7 +6045,13 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                ALC292_STANDARD_PINS,
                {0x13, 0x90a60140}),
        SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
-               ALC295_STANDARD_PINS),
+               ALC295_STANDARD_PINS,
+               {0x17, 0x21014020},
+               {0x18, 0x21a19030}),
+       SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+               ALC295_STANDARD_PINS,
+               {0x17, 0x21014040},
+               {0x18, 0x21a19050}),
        SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC298_STANDARD_PINS,
                {0x17, 0x90170110}),
@@ -6613,6 +6625,7 @@ enum {
        ALC891_FIXUP_HEADSET_MODE,
        ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
        ALC662_FIXUP_ACER_VERITON,
+       ALC892_FIXUP_ASROCK_MOBO,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -6889,6 +6902,16 @@ static const struct hda_fixup alc662_fixups[] = {
                        { }
                }
        },
+       [ALC892_FIXUP_ASROCK_MOBO] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x15, 0x40f000f0 }, /* disabled */
+                       { 0x16, 0x40f000f0 }, /* disabled */
+                       { 0x18, 0x01014011 }, /* LO */
+                       { 0x1a, 0x01014012 }, /* LO */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6926,6 +6949,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
+       SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
        SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
        SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
        SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
index c60a776..8a59d47 100644 (file)
@@ -2907,6 +2907,23 @@ AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"),
 AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"),
 AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
 
+/* Syntek STK1160 */
+{
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+                      USB_DEVICE_ID_MATCH_INT_CLASS |
+                      USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+       .idVendor = 0x05e1,
+       .idProduct = 0x0408,
+       .bInterfaceClass = USB_CLASS_AUDIO,
+       .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .vendor_name = "Syntek",
+               .product_name = "STK1160",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_AUDIO_ALIGN_TRANSFER
+       }
+},
+
 /* Digidesign Mbox */
 {
        /* Thanks to Clemens Ladisch <clemens@ladisch.de> */
index 1188bc8..a396292 100644 (file)
 #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 
 #define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
+#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
+#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
index c0c0b26..b63a31b 100644 (file)
@@ -98,6 +98,15 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
                        *type = INSN_FP_SETUP;
                break;
 
+       case 0x8d:
+               if (insn.rex_prefix.bytes &&
+                   insn.rex_prefix.bytes[0] == 0x48 &&
+                   insn.modrm.nbytes && insn.modrm.bytes[0] == 0x2c &&
+                   insn.sib.nbytes && insn.sib.bytes[0] == 0x24)
+                       /* lea %(rsp), %rbp */
+                       *type = INSN_FP_SETUP;
+               break;
+
        case 0x90:
                *type = INSN_NOP;
                break;
index 143b6cd..e8a1f69 100644 (file)
@@ -97,6 +97,19 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
        return next;
 }
 
+static bool gcov_enabled(struct objtool_file *file)
+{
+       struct section *sec;
+       struct symbol *sym;
+
+       list_for_each_entry(sec, &file->elf->sections, list)
+               list_for_each_entry(sym, &sec->symbol_list, list)
+                       if (!strncmp(sym->name, "__gcov_.", 8))
+                               return true;
+
+       return false;
+}
+
 #define for_each_insn(file, insn)                                      \
        list_for_each_entry(insn, &file->insn_list, list)
 
@@ -713,6 +726,7 @@ static struct rela *find_switch_table(struct objtool_file *file,
                                      struct instruction *insn)
 {
        struct rela *text_rela, *rodata_rela;
+       struct instruction *orig_insn = insn;
 
        text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
        if (text_rela && text_rela->sym == file->rodata->sym) {
@@ -733,10 +747,16 @@ static struct rela *find_switch_table(struct objtool_file *file,
 
        /* case 3 */
        func_for_each_insn_continue_reverse(file, func, insn) {
-               if (insn->type == INSN_JUMP_UNCONDITIONAL ||
-                   insn->type == INSN_JUMP_DYNAMIC)
+               if (insn->type == INSN_JUMP_DYNAMIC)
                        break;
 
+               /* allow small jumps within the range */
+               if (insn->type == INSN_JUMP_UNCONDITIONAL &&
+                   insn->jump_dest &&
+                   (insn->jump_dest->offset <= insn->offset ||
+                    insn->jump_dest->offset > orig_insn->offset))
+                   break;
+
                text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
                                                    insn->len);
                if (text_rela && text_rela->sym == file->rodata->sym)
@@ -1034,34 +1054,6 @@ static int validate_branch(struct objtool_file *file,
        return 0;
 }
 
-static bool is_gcov_insn(struct instruction *insn)
-{
-       struct rela *rela;
-       struct section *sec;
-       struct symbol *sym;
-       unsigned long offset;
-
-       rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
-       if (!rela)
-               return false;
-
-       if (rela->sym->type != STT_SECTION)
-               return false;
-
-       sec = rela->sym->sec;
-       offset = rela->addend + insn->offset + insn->len - rela->offset;
-
-       list_for_each_entry(sym, &sec->symbol_list, list) {
-               if (sym->type != STT_OBJECT)
-                       continue;
-
-               if (offset >= sym->offset && offset < sym->offset + sym->len)
-                       return (!memcmp(sym->name, "__gcov0.", 8));
-       }
-
-       return false;
-}
-
 static bool is_kasan_insn(struct instruction *insn)
 {
        return (insn->type == INSN_CALL &&
@@ -1083,9 +1075,6 @@ static bool ignore_unreachable_insn(struct symbol *func,
        if (insn->type == INSN_NOP)
                return true;
 
-       if (is_gcov_insn(insn))
-               return true;
-
        /*
         * Check if this (or a subsequent) instruction is related to
         * CONFIG_UBSAN or CONFIG_KASAN.
@@ -1146,6 +1135,19 @@ static int validate_functions(struct objtool_file *file)
                                    ignore_unreachable_insn(func, insn))
                                        continue;
 
+                               /*
+                                * gcov produces a lot of unreachable
+                                * instructions.  If we get an unreachable
+                                * warning and the file has gcov enabled, just
+                                * ignore it, and all other such warnings for
+                                * the file.
+                                */
+                               if (!file->ignore_unreachables &&
+                                   gcov_enabled(file)) {
+                                       file->ignore_unreachables = true;
+                                       continue;
+                               }
+
                                WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
                                warnings++;
                        }
index 5ce61a1..df14e6b 100644 (file)
@@ -36,7 +36,7 @@ SOLIBEXT=so
 # The following works at least on fedora 23, you may need the next
 # line for other distros.
 ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
-JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | cut -d ' ' -f 3)
+JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
 else
   ifneq (,$(wildcard /usr/sbin/alternatives))
     JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
index fb8e42c..4ffff7b 100644 (file)
@@ -601,7 +601,8 @@ int hist_browser__run(struct hist_browser *browser, const char *help)
                        u64 nr_entries;
                        hbt->timer(hbt->arg);
 
-                       if (hist_browser__has_filter(browser))
+                       if (hist_browser__has_filter(browser) ||
+                           symbol_conf.report_hierarchy)
                                hist_browser__update_nr_entries(browser);
 
                        nr_entries = hist_browser__nr_entries(browser);
index 85dd0db..2f3eded 100644 (file)
@@ -1895,7 +1895,6 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
        if (ph->needs_swap)
                nr = bswap_32(nr);
 
-       ph->env.nr_numa_nodes = nr;
        nodes = zalloc(sizeof(*nodes) * nr);
        if (!nodes)
                return -ENOMEM;
@@ -1932,6 +1931,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
 
                free(str);
        }
+       ph->env.nr_numa_nodes = nr;
        ph->env.numa_nodes = nodes;
        return 0;
 
index 9f43fda..660fca0 100644 (file)
@@ -136,8 +136,8 @@ do {                                                        \
 group          [^,{}/]*[{][^}]*[}][^,{}/]*
 event_pmu      [^,{}/]+[/][^/]*[/][^,{}/]*
 event          [^,{}/]+
-bpf_object     .*\.(o|bpf)
-bpf_source     .*\.c
+bpf_object     [^,{}]+\.(o|bpf)
+bpf_source     [^,{}]+\.c
 
 num_dec                [0-9]+
 num_hex                0x[a-fA-F0-9]+
index db96688..8035cc1 100644 (file)
@@ -84,7 +84,8 @@ static void async_pf_execute(struct work_struct *work)
         * mm and might be done in another context, so we must
         * use FOLL_REMOTE.
         */
-       __get_user_pages_unlocked(NULL, mm, addr, 1, 1, 0, NULL, FOLL_REMOTE);
+       __get_user_pages_unlocked(NULL, mm, addr, 1, NULL,
+                       FOLL_WRITE | FOLL_REMOTE);
 
        kvm_async_page_present_sync(vcpu, apf);
 
index 81dfc73..2907b7b 100644 (file)
@@ -1346,21 +1346,19 @@ unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *w
 static int get_user_page_nowait(unsigned long start, int write,
                struct page **page)
 {
-       int flags = FOLL_TOUCH | FOLL_NOWAIT | FOLL_HWPOISON | FOLL_GET;
+       int flags = FOLL_NOWAIT | FOLL_HWPOISON;
 
        if (write)
                flags |= FOLL_WRITE;
 
-       return __get_user_pages(current, current->mm, start, 1, flags, page,
-                       NULL, NULL);
+       return get_user_pages(start, 1, flags, page, NULL);
 }
 
 static inline int check_user_page_hwpoison(unsigned long addr)
 {
-       int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE;
+       int rc, flags = FOLL_HWPOISON | FOLL_WRITE;
 
-       rc = __get_user_pages(current, current->mm, addr, 1,
-                             flags, NULL, NULL, NULL);
+       rc = get_user_pages(addr, 1, flags, NULL, NULL);
        return rc == -EHWPOISON;
 }
 
@@ -1416,10 +1414,15 @@ static int hva_to_pfn_slow(unsigned long addr, bool *async, bool write_fault,
                down_read(&current->mm->mmap_sem);
                npages = get_user_page_nowait(addr, write_fault, page);
                up_read(&current->mm->mmap_sem);
-       } else
+       } else {
+               unsigned int flags = FOLL_TOUCH | FOLL_HWPOISON;
+
+               if (write_fault)
+                       flags |= FOLL_WRITE;
+
                npages = __get_user_pages_unlocked(current, current->mm, addr, 1,
-                                                  write_fault, 0, page,
-                                                  FOLL_TOUCH|FOLL_HWPOISON);
+                                                  page, flags);
+       }
        if (npages != 1)
                return npages;