]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'kvm-ppc-next-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/paulu...
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 31 Mar 2020 14:45:49 +0000 (10:45 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 31 Mar 2020 14:45:49 +0000 (10:45 -0400)
KVM PPC update for 5.7

* Add a capability for enabling secure guests under the Protected
  Execution Framework ultravisor

* Various bug fixes and cleanups.

685 files changed:
.gitignore
COPYING
CREDITS
Documentation/admin-guide/bootconfig.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/arm64/memory.rst
Documentation/arm64/tagged-address-abi.rst
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.yaml
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/net/mdio.yaml
Documentation/filesystems/zonefs.txt
Documentation/hwmon/xdpe12284.rst
Documentation/kbuild/makefiles.rst
Documentation/networking/phy.rst
Documentation/power/index.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/sphinx/parallel-wrapper.sh
Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst
Documentation/virt/kvm/api.rst
Documentation/virt/kvm/arm/hyp-abi.rst
Documentation/x86/index.rst
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/configs/axm55xx_defconfig
arch/arm/include/asm/arch_gicv3.h
arch/arm/include/asm/kvm_arm.h [deleted file]
arch/arm/include/asm/kvm_asm.h [deleted file]
arch/arm/include/asm/kvm_coproc.h [deleted file]
arch/arm/include/asm/kvm_emulate.h [deleted file]
arch/arm/include/asm/kvm_host.h [deleted file]
arch/arm/include/asm/kvm_hyp.h [deleted file]
arch/arm/include/asm/kvm_mmu.h [deleted file]
arch/arm/include/asm/kvm_ras.h [deleted file]
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/sections.h
arch/arm/include/asm/stage2_pgtable.h [deleted file]
arch/arm/include/asm/virt.h
arch/arm/include/uapi/asm/kvm.h [deleted file]
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/hyp-stub.S
arch/arm/kernel/vmlinux-xip.lds.S
arch/arm/kernel/vmlinux.lds.S
arch/arm/kernel/vmlinux.lds.h
arch/arm/kvm/Kconfig [deleted file]
arch/arm/kvm/Makefile [deleted file]
arch/arm/kvm/coproc.c [deleted file]
arch/arm/kvm/coproc.h [deleted file]
arch/arm/kvm/coproc_a15.c [deleted file]
arch/arm/kvm/coproc_a7.c [deleted file]
arch/arm/kvm/emulate.c [deleted file]
arch/arm/kvm/guest.c [deleted file]
arch/arm/kvm/handle_exit.c [deleted file]
arch/arm/kvm/hyp/Makefile [deleted file]
arch/arm/kvm/hyp/banked-sr.c [deleted file]
arch/arm/kvm/hyp/cp15-sr.c [deleted file]
arch/arm/kvm/hyp/entry.S [deleted file]
arch/arm/kvm/hyp/hyp-entry.S [deleted file]
arch/arm/kvm/hyp/s2-setup.c [deleted file]
arch/arm/kvm/hyp/switch.c [deleted file]
arch/arm/kvm/hyp/tlb.c [deleted file]
arch/arm/kvm/hyp/vfp.S [deleted file]
arch/arm/kvm/init.S [deleted file]
arch/arm/kvm/interrupts.S [deleted file]
arch/arm/kvm/irq.h [deleted file]
arch/arm/kvm/reset.c [deleted file]
arch/arm/kvm/trace.h [deleted file]
arch/arm/kvm/vgic-v3-coproc.c [deleted file]
arch/arm/mach-exynos/Kconfig
arch/arm/mm/mmu.c
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/lse.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/virt.h
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c
arch/csky/Kconfig
arch/csky/Kconfig.platforms [new file with mode: 0644]
arch/csky/abiv1/inc/abi/cacheflush.h
arch/csky/abiv1/inc/abi/entry.h
arch/csky/abiv2/cacheflush.c
arch/csky/abiv2/inc/abi/cacheflush.h
arch/csky/abiv2/inc/abi/entry.h
arch/csky/configs/defconfig
arch/csky/include/asm/Kbuild
arch/csky/include/asm/cache.h
arch/csky/include/asm/cacheflush.h
arch/csky/include/asm/fixmap.h
arch/csky/include/asm/memory.h [new file with mode: 0644]
arch/csky/include/asm/mmu.h
arch/csky/include/asm/mmu_context.h
arch/csky/include/asm/pci.h [new file with mode: 0644]
arch/csky/include/asm/pgtable.h
arch/csky/include/asm/stackprotector.h [new file with mode: 0644]
arch/csky/include/asm/tcm.h [new file with mode: 0644]
arch/csky/include/uapi/asm/unistd.h
arch/csky/kernel/atomic.S
arch/csky/kernel/process.c
arch/csky/kernel/setup.c
arch/csky/kernel/smp.c
arch/csky/kernel/time.c
arch/csky/kernel/vmlinux.lds.S
arch/csky/mm/Makefile
arch/csky/mm/cachev1.c
arch/csky/mm/cachev2.c
arch/csky/mm/highmem.c
arch/csky/mm/init.c
arch/csky/mm/syscache.c
arch/csky/mm/tcm.c [new file with mode: 0644]
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/ingenic/jz4780.dtsi
arch/mips/boot/dts/ingenic/x1000.dtsi
arch/mips/include/asm/sync.h
arch/mips/kernel/vpe.c
arch/mips/vdso/Makefile
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_32.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/book3s32/hash_low.S
arch/powerpc/mm/book3s32/mmu.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/xmon/xmon.c
arch/riscv/boot/.gitignore
arch/riscv/include/asm/csr.h
arch/riscv/kernel/head.S
arch/riscv/kernel/traps.c
arch/riscv/mm/kasan_init.c
arch/s390/Makefile
arch/s390/boot/Makefile
arch/s390/boot/kaslr.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/page.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/qdio.h
arch/s390/kvm/gaccess.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/gmap.c
arch/x86/boot/compressed/kaslr_64.c
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/ima_arch.c
arch/x86/kernel/kvm.c
arch/x86/kvm/Kconfig
arch/x86/kvm/Makefile
arch/x86/kvm/cpuid.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/nested.h
arch/x86/kvm/vmx/vmenter.S
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/xen/enlighten_pv.c
block/blk-flush.c
block/blk-mq-sched.c
block/blk-mq-tag.c
block/blk-mq-tag.h
block/blk-mq.c
block/blk-mq.h
crypto/hash_info.c
drivers/acpi/acpi_watchdog.c
drivers/acpi/acpica/evevent.c
drivers/acpi/sleep.c
drivers/block/floppy.c
drivers/block/null_blk.h
drivers/block/null_blk_main.c
drivers/block/paride/pcd.c
drivers/cdrom/gdrom.c
drivers/char/tpm/Makefile
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_tis_spi_main.c [moved from drivers/char/tpm/tpm_tis_spi.c with 100% similarity]
drivers/cpufreq/cpufreq.c
drivers/devfreq/devfreq.c
drivers/fsi/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_phys.c
drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
drivers/gpu/drm/i915/gt/intel_gt_requests.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring.c
drivers/gpu/drm/i915/gt/intel_ring.h
drivers/gpu/drm/i915/gt/intel_ring_types.h
drivers/gpu/drm/i915/gt/selftest_lrc.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_scheduler.c
drivers/gpu/drm/i915/i915_utils.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
drivers/gpu/drm/panfrost/panfrost_job.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/selftests/drm_cmdline_selftests.h
drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
drivers/hid/hid-alps.c
drivers/hid/hid-apple.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-ite.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/w83627ehf.c
drivers/i2c/busses/i2c-altera.c
drivers/i2c/busses/i2c-jz4780.c
drivers/ide/ide-gd.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/iommu/Makefile
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/qcom_iommu.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic-v4.c
drivers/macintosh/therm_windtunnel.c
drivers/misc/habanalabs/device.c
drivers/misc/habanalabs/goya/goya.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
drivers/net/ethernet/aquantia/atlantic/aq_filters.c
drivers/net/ethernet/aquantia/atlantic/aq_hw.h
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
drivers/net/ethernet/broadcom/cnic_defs.h
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.h
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
drivers/net/ethernet/huawei/hinic/hinic_main.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
drivers/net/ethernet/mellanox/mlx5/core/en/health.c
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.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/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag.h
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
drivers/net/ethernet/mellanox/mlx5/core/wq.c
drivers/net/ethernet/mellanox/mlx5/core/wq.h
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/mscc/ocelot_board.c
drivers/net/ethernet/pensando/ionic/ionic_dev.c
drivers/net/ethernet/pensando/ionic/ionic_if.h
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_rdma.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/xilinx/ll_temac.h
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/broadcom.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-bcm-iproc.c
drivers/net/phy/mscc.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy_device.c
drivers/net/slip/slip.c
drivers/net/usb/qmi_wwan.c
drivers/net/wireguard/device.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/send.c
drivers/net/wireguard/socket.c
drivers/nfc/pn544/i2c.c
drivers/nfc/pn544/pn544.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/pci/controller/pcie-brcmstb.c
drivers/platform/chrome/wilco_ec/properties.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/qdio_setup.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/sd_zbc.c
drivers/scsi/sr.c
drivers/staging/android/Kconfig
drivers/staging/android/Makefile
drivers/staging/android/TODO
drivers/staging/android/ashmem.c
drivers/staging/android/uapi/vsoc_shm.h [deleted file]
drivers/staging/android/vsoc.c [deleted file]
drivers/staging/greybus/audio_manager.c
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/staging/vt6656/dpc.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_transport.c
drivers/tee/amdtee/Kconfig
drivers/thunderbolt/switch.c
drivers/tty/serdev/serdev-ttyport.c
drivers/tty/serial/8250/8250_aspeed_vuart.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_of.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/imx.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial-tegra.c
drivers/tty/tty_port.c
drivers/tty/vt/selection.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/quirks.c
drivers/usb/core/usb.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/debug.h
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_audio.c
drivers/usb/gadget/function/u_serial.c
drivers/usb/gadget/udc/udc-xilinx.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/serial/ch341.c
drivers/usb/serial/ir-usb.c
drivers/usb/storage/uas.c
drivers/vhost/net.c
drivers/watchdog/Kconfig
drivers/watchdog/da9062_wdt.c
drivers/watchdog/wdat_wdt.c
drivers/xen/preempt.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/qgroup.h
fs/btrfs/transaction.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/ext4/balloc.c
fs/ext4/ext4.h
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/jbd2/transaction.c
fs/pipe.c
fs/zonefs/Kconfig
fs/zonefs/super.c
include/acpi/acpixf.h
include/acpi/actypes.h
include/kvm/arm_vgic.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/bootconfig.h
include/linux/compat.h
include/linux/hid.h
include/linux/icmpv6.h
include/linux/intel-svm.h
include/linux/irqchip/arm-gic-common.h
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic-v4.h
include/linux/irqdomain.h
include/linux/ktime.h
include/linux/kvm_host.h
include/linux/mlx5/mlx5_ifc.h
include/linux/netdevice.h
include/linux/netfilter/ipset/ip_set.h
include/linux/rculist_nulls.h
include/linux/skbuff.h
include/linux/swiotlb.h
include/linux/time32.h
include/linux/timekeeping32.h
include/linux/tty.h
include/linux/types.h
include/linux/usb/quirks.h
include/net/flow_dissector.h
include/net/sock.h
include/scsi/iscsi_proto.h
include/sound/rawmidi.h
include/sound/soc-dapm.h
include/uapi/asm-generic/posix_types.h
include/uapi/linux/bpf.h
include/uapi/linux/netfilter/nf_conntrack_common.h
include/uapi/linux/swab.h
include/uapi/linux/time.h
include/uapi/linux/usb/charger.h
init/Kconfig
init/main.c
ipc/sem.c
kernel/audit.c
kernel/auditfilter.c
kernel/bpf/btf.c
kernel/bpf/hashtab.c
kernel/bpf/offload.c
kernel/compat.c
kernel/dma/contiguous.c
kernel/dma/direct.c
kernel/dma/swiotlb.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/proc.c
kernel/power/snapshot.c
kernel/signal.c
kernel/sysctl.c
kernel/time/time.c
kernel/trace/Kconfig
kernel/trace/blktrace.c
kernel/trace/synth_event_gen_test.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
lib/bootconfig.c
lib/crypto/chacha20poly1305.c
lib/stackdepot.c
lib/string.c
mm/memcontrol.c
mm/mmap.c
mm/mremap.c
mm/shmem.c
mm/sparse.c
mm/swapfile.c
mm/vmscan.c
net/Kconfig
net/bridge/br_device.c
net/bridge/br_stp.c
net/core/dev.c
net/core/devlink.c
net/core/fib_rules.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ethtool/bitset.c
net/ethtool/bitset.h
net/hsr/hsr_framereg.c
net/ipv4/cipso_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipv6_sockglue.c
net/ipv6/route.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mptcp/Kconfig
net/mptcp/protocol.c
net/mptcp/protocol.h
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nft_set_pipapo.c
net/netfilter/xt_hashlimit.c
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/openvswitch/datapath.c
net/openvswitch/flow_netlink.c
net/openvswitch/flow_table.c
net/openvswitch/meter.c
net/openvswitch/vport.c
net/rds/rdma.c
net/sched/act_api.c
net/sched/cls_flower.c
net/sctp/sm_statefuns.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/tls/tls_device.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/nl80211.c
net/wireless/reg.c
net/xdp/xsk.c
net/xdp/xsk_queue.h
scripts/Makefile.lib
scripts/get_maintainer.pl
security/integrity/ima/Kconfig
security/integrity/platform_certs/load_uefi.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_queue.c
sound/core/seq/seq_timer.c
sound/core/seq/seq_timer.h
sound/hda/ext/hdac_ext_controller.c
sound/hda/hdmi_chmap.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_sysfs.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-i2s.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/raven/pci-acp3x.c
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/max98090.c
sound/soc/codecs/max98090.h
sound/soc/fsl/fsl_sai.c
sound/soc/soc-dapm.c
sound/soc/sof/intel/hda-codec.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/hda.c
sound/soc/sunxi/sun8i-codec.c
tools/bootconfig/include/linux/printk.h
tools/bootconfig/main.c
tools/bootconfig/samples/bad-mixed-kv1.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-mixed-kv2.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-samekey.bconf [new file with mode: 0644]
tools/bootconfig/test-bootconfig.sh
tools/include/uapi/linux/bpf.h
tools/kvm/kvm_stat/kvm_stat
tools/kvm/kvm_stat/kvm_stat.txt
tools/lib/bpf/libbpf.c
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/prog_tests/select_reuseport.c
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/futex/functional/Makefile
tools/testing/selftests/kvm/demand_paging_test.c
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/steal_time.c
tools/testing/selftests/lib.mk
tools/testing/selftests/livepatch/Makefile
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/forwarding/mirror_gre.sh
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/netfilter/nft_concat_range.sh
tools/testing/selftests/openat2/helpers.c
tools/testing/selftests/openat2/resolve_test.c
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rtc/Makefile
tools/testing/selftests/timens/Makefile
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/test_space.sh
tools/testing/selftests/vm/run_vmtests
tools/testing/selftests/wireguard/qemu/Makefile
virt/kvm/arm/arch_timer.c
virt/kvm/arm/arm.c
virt/kvm/arm/trace.h
virt/kvm/arm/vgic/vgic-debug.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic-v4.c
virt/kvm/arm/vgic/vgic.h
virt/kvm/kvm_main.c

index 72ef86a5570d28015d0ccb95ccd212bf8820c1c2..2763fce8766c09417fa6a4b9885e04a66c409b03 100644 (file)
@@ -100,6 +100,10 @@ modules.order
 /include/ksym/
 /arch/*/include/generated/
 
+# Generated lkdtm tests
+/tools/testing/selftests/lkdtm/*.sh
+!/tools/testing/selftests/lkdtm/run.sh
+
 # stgit generated dirs
 patches-*
 
diff --git a/COPYING b/COPYING
index da4cb28febe66172a9fdf1a235525ae6c00cde1d..a635a38ef9405fdfcfe97f3a435393c1e9cae971 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -16,3 +16,5 @@ In addition, other licenses may also apply. Please see:
        Documentation/process/license-rules.rst
 
 for more details.
+
+All contributions to the Linux Kernel are subject to this COPYING file.
diff --git a/CREDITS b/CREDITS
index a97d3280a627b3665e68c94a574409f71cee1da6..032b5994f4760a13770d1629b8b057195d9266c2 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -567,6 +567,11 @@ D: Original author of Amiga FFS filesystem
 S: Orlando, Florida
 S: USA
 
+N: Paul Burton
+E: paulburton@kernel.org
+W: https://pburton.com
+D: MIPS maintainer 2018-2020
+
 N: Lennert Buytenhek
 E: kernel@wantstofly.org
 D: Original (2.4) rewrite of the ethernet bridging code
index b342a679639277c41100b13d9cdf6b88d70040b8..cf2edcd09183bef328294cbe67b28983149d283f 100644 (file)
@@ -62,6 +62,30 @@ Or more shorter, written as following::
 In both styles, same key words are automatically merged when parsing it
 at boot time. So you can append similar trees or key-values.
 
+Same-key Values
+---------------
+
+It is prohibited that two or more values or arrays share a same-key.
+For example,::
+
+ foo = bar, baz
+ foo = qux  # !ERROR! we can not re-define same key
+
+If you want to append the value to existing key as an array member,
+you can use ``+=`` operator. For example::
+
+ foo = bar, baz
+ foo += qux
+
+In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``.
+
+However, a sub-key and a value can not co-exist under a parent key.
+For example, following config is NOT allowed.::
+
+ foo = value1
+ foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist
+
+
 Comments
 --------
 
@@ -102,9 +126,13 @@ Boot Kernel With a Boot Config
 ==============================
 
 Since the boot configuration file is loaded with initrd, it will be added
-to the end of the initrd (initramfs) image file. The Linux kernel decodes
-the last part of the initrd image in memory to get the boot configuration
-data.
+to the end of the initrd (initramfs) image file with size, checksum and
+12-byte magic word as below.
+
+[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
+
+The Linux kernel decodes the last part of the initrd image in memory to
+get the boot configuration data.
 Because of this "piggyback" method, there is no need to change or
 update the boot loader and the kernel image itself.
 
index b0beae9b9e367216fbdbdfeb3da70ce85aa9a91f..144c1305a4f89ed68bd74516b0bd5f5e9501d11e 100644 (file)
                        dynamic table installation which will install SSDT
                        tables to /sys/firmware/acpi/tables/dynamic.
 
+       acpi_no_watchdog        [HW,ACPI,WDT]
+                       Ignore the ACPI-based watchdog interface (WDAT) and let
+                       a native driver control the watchdog device instead.
+
        acpi_rsdp=      [ACPI,EFI,KEXEC]
                        Pass the RSDP address to the kernel, mostly used
                        on machines running EFI runtime service to boot the
index 02e02175e6f56a75da568cd0112bf71769b8f938..cf03b3290800c25ea7c5d8cba093b0189e3d727a 100644 (file)
@@ -129,7 +129,7 @@ this logic.
 
 As a single binary will need to support both 48-bit and 52-bit VA
 spaces, the VMEMMAP must be sized large enough for 52-bit VAs and
-also must be sized large enought to accommodate a fixed PAGE_OFFSET.
+also must be sized large enough to accommodate a fixed PAGE_OFFSET.
 
 Most code in the kernel should not need to consider the VA_BITS, for
 code that does need to know the VA size the variables are
index d4a85d535bf99e09cfe5c3dc41652eaa3b64f21b..4a9d9c794ee5d889638d1a3af008dec06d11feaf 100644 (file)
@@ -44,8 +44,15 @@ The AArch64 Tagged Address ABI has two stages of relaxation depending
 how the user addresses are used by the kernel:
 
 1. User addresses not accessed by the kernel but used for address space
-   management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
-   of valid tagged pointers in this context is always allowed.
+   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
+   tagged pointers in this context is allowed with the exception of
+   ``brk()``, ``mmap()`` and the ``new_address`` argument to
+   ``mremap()`` as these have the potential to alias with existing
+   user addresses.
+
+   NOTE: This behaviour changed in v5.6 and so some earlier kernels may
+   incorrectly accept valid tagged pointers for the ``brk()``,
+   ``mmap()`` and ``mremap()`` system calls.
 
 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
    relaxation is disabled by default and the application thread needs to
index 7cd56a1993b14ad75e5d21c5b3c23c29bee8f1cb..607758a66a99cc04b6abb71b3f3d610a3ccaf26c 100644 (file)
@@ -551,6 +551,7 @@ options to your ``.config``:
 Once the kernel is built and installed, a simple
 
 .. code-block:: bash
+
        modprobe example-test
 
 ...will run the tests.
index 86ad617d2327d459bd6c11c95705248f35b9df0d..5ff9cf26ca380b4886a8848ee308e3f8a9838f6a 100644 (file)
@@ -43,9 +43,13 @@ properties:
         - enum:
           - allwinner,sun8i-h3-tcon-tv
           - allwinner,sun50i-a64-tcon-tv
-          - allwinner,sun50i-h6-tcon-tv
         - const: allwinner,sun8i-a83t-tcon-tv
 
+      - items:
+        - enum:
+          - allwinner,sun50i-h6-tcon-tv
+        - const: allwinner,sun8i-r40-tcon-tv
+
   reg:
     maxItems: 1
 
index 9af873b43acd8742ade8ed944e2cfea4ec045369..8453ee340b9fb0abffb19f48c95391bb0e93e9c9 100644 (file)
@@ -33,24 +33,40 @@ properties:
     maxItems: 1
 
   clocks:
-    minItems: 2
-    maxItems: 3
-    items:
-      - description: The CSI interface clock
-      - description: The CSI ISP clock
-      - description: The CSI DRAM clock
+    oneOf:
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI DRAM clock
+
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI ISP clock
+        - description: The CSI DRAM clock
 
   clock-names:
-    minItems: 2
-    maxItems: 3
-    items:
-      - const: bus
-      - const: isp
-      - const: ram
+    oneOf:
+      - items:
+        - const: bus
+        - const: ram
+
+      - items:
+        - const: bus
+        - const: isp
+        - const: ram
 
   resets:
     maxItems: 1
 
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnects:
+    maxItems: 1
+
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnect-names:
+    const: dma-mem
+
   # See ./video-interfaces.txt for details
   port:
     type: object
index dd1843489ad15075fa2b31c48fa00e18d40ae032..3e0a8a92d6529ef6f2ed0901b9264e1496f7d3b8 100644 (file)
@@ -347,6 +347,7 @@ examples:
         interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 
         #iommu-cells = <1>;
+        #reset-cells = <1>;
     };
 
     external-memory-controller@7001b000 {
@@ -363,20 +364,23 @@ examples:
             timing-0 {
                 clock-frequency = <12750000>;
 
-                nvidia,emc-zcal-cnt-long = <0x00000042>;
-                nvidia,emc-auto-cal-interval = <0x001fffff>;
-                nvidia,emc-ctt-term-ctrl = <0x00000802>;
-                nvidia,emc-cfg = <0x73240000>;
-                nvidia,emc-cfg-2 = <0x000008c5>;
-                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
-                nvidia,emc-bgbias-ctl0 = <0x00000008>;
                 nvidia,emc-auto-cal-config = <0xa1430000>;
                 nvidia,emc-auto-cal-config2 = <0x00000000>;
                 nvidia,emc-auto-cal-config3 = <0x00000000>;
-                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-auto-cal-interval = <0x001fffff>;
+                nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                nvidia,emc-cfg = <0x73240000>;
+                nvidia,emc-cfg-2 = <0x000008c5>;
+                nvidia,emc-ctt-term-ctrl = <0x00000802>;
                 nvidia,emc-mode-1 = <0x80100003>;
                 nvidia,emc-mode-2 = <0x80200008>;
                 nvidia,emc-mode-4 = <0x00000000>;
+                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                nvidia,emc-zcal-cnt-long = <0x00000042>;
+                nvidia,emc-zcal-interval = <0x00000000>;
 
                 nvidia,emc-configuration = <
                     0x00000000 /* EMC_RC */
index 19f5508a75696b722624c550700ee74f72b2362f..4a9145ef15d6b4a4485649eb85757445aa0bffb6 100644 (file)
@@ -124,7 +124,7 @@ not every application needs SDIO irq, e.g. MMC cards.
                pinctrl-1 = <&mmc1_idle>;
                pinctrl-2 = <&mmc1_sleep>;
                ...
-               interrupts-extended = <&intc 64 &gpio2 28 GPIO_ACTIVE_LOW>;
+               interrupts-extended = <&intc 64 &gpio2 28 IRQ_TYPE_LEVEL_LOW>;
        };
 
        mmc1_idle : pinmux_cirq_pin {
index 5d08d2ffd4ebcc0af0d542fa2d00700f5382b555..50c3397a82bc4cea8efc364827c4fefb0e0838f8 100644 (file)
@@ -56,7 +56,6 @@ patternProperties:
 examples:
   - |
     davinci_mdio: mdio@5c030000 {
-        compatible = "ti,davinci_mdio";
         reg = <0x5c030000 0x1000>;
         #address-cells = <1>;
         #size-cells = <0>;
index 935bf22031ca1ce8ea2df2cfc8cd6cb6a33d672b..d54fa98ac1582866ecb7abc4cf19d0790ea3673d 100644 (file)
@@ -134,7 +134,7 @@ Sequential zone files can only be written sequentially, starting from the file
 end, that is, write operations can only be append writes. Zonefs makes no
 attempt at accepting random writes and will fail any write request that has a
 start offset not corresponding to the end of the file, or to the end of the last
-write issued and still in-flight (for asynchrnous I/O operations).
+write issued and still in-flight (for asynchronous I/O operations).
 
 Since dirty page writeback by the page cache does not guarantee a sequential
 write pattern, zonefs prevents buffered writes and writeable shared mappings
@@ -142,7 +142,7 @@ on sequential files. Only direct I/O writes are accepted for these files.
 zonefs relies on the sequential delivery of write I/O requests to the device
 implemented by the block layer elevator. An elevator implementing the sequential
 write feature for zoned block device (ELEVATOR_F_ZBD_SEQ_WRITE elevator feature)
-must be used. This type of elevator (e.g. mq-deadline) is the set by default
+must be used. This type of elevator (e.g. mq-deadline) is set by default
 for zoned block devices on device initialization.
 
 There are no restrictions on the type of I/O used for read operations in
@@ -196,7 +196,7 @@ additional conditions that result in I/O errors.
   may still happen in the case of a partial failure of a very large direct I/O
   operation split into multiple BIOs/requests or asynchronous I/O operations.
   If one of the write request within the set of sequential write requests
-  issued to the device fails, all write requests after queued after it will
+  issued to the device fails, all write requests queued after it will
   become unaligned and fail.
 
 * Delayed write errors: similarly to regular block devices, if the device side
@@ -207,7 +207,7 @@ additional conditions that result in I/O errors.
   causing all data to be dropped after the sector that caused the error.
 
 All I/O errors detected by zonefs are notified to the user with an error code
-return for the system call that trigered or detected the error. The recovery
+return for the system call that triggered or detected the error. The recovery
 actions taken by zonefs in response to I/O errors depend on the I/O type (read
 vs write) and on the reason for the error (bad sector, unaligned writes or zone
 condition change).
@@ -222,7 +222,7 @@ condition change).
 * A zone condition change to read-only or offline also always triggers zonefs
   I/O error recovery.
 
-Zonefs minimal I/O error recovery may change a file size and file access
+Zonefs minimal I/O error recovery may change a file size and file access
 permissions.
 
 * File size changes:
@@ -237,7 +237,7 @@ permissions.
   A file size may also be reduced to reflect a delayed write error detected on
   fsync(): in this case, the amount of data effectively written in the zone may
   be less than originally indicated by the file inode size. After such I/O
-  error, zonefs always fixes a file inode size to reflect the amount of data
+  error, zonefs always fixes the file inode size to reflect the amount of data
   persistently stored in the file zone.
 
 * Access permission changes:
@@ -281,11 +281,11 @@ Further notes:
   permissions to read-only applies to all files. The file system is remounted
   read-only.
 * Access permission and file size changes due to the device transitioning zones
-  to the offline condition are permanent. Remounting or reformating the device
+  to the offline condition are permanent. Remounting or reformatting the device
   with mkfs.zonefs (mkzonefs) will not change back offline zone files to a good
   state.
 * File access permission changes to read-only due to the device transitioning
-  zones to the read-only condition are permanent. Remounting or reformating
+  zones to the read-only condition are permanent. Remounting or reformatting
   the device will not re-enable file write access.
 * File access permission changes implied by the remount-ro, zone-ro and
   zone-offline mount options are temporary for zones in a good condition.
@@ -301,13 +301,13 @@ Mount options
 
 zonefs define the "errors=<behavior>" mount option to allow the user to specify
 zonefs behavior in response to I/O errors, inode size inconsistencies or zone
-condition chages. The defined behaviors are as follow:
+condition changes. The defined behaviors are as follow:
 * remount-ro (default)
 * zone-ro
 * zone-offline
 * repair
 
-The I/O error actions defined for each behavior is detailed in the previous
+The I/O error actions defined for each behavior are detailed in the previous
 section.
 
 Zonefs User Space Tools
index 6b7ae98cc536f6382a947436f3ede87a3b112fdc..67d1f87808e57981a18c55c4877d6ab80659f5ce 100644 (file)
@@ -24,6 +24,7 @@ This driver implements support for Infineon Multi-phase XDPE122 family
 dual loop voltage regulators.
 The family includes XDPE12284 and XDPE12254 devices.
 The devices from this family complaint with:
+
 - Intel VR13 and VR13HC rev 1.3, IMVP8 rev 1.2 and IMPVP9 rev 1.3 DC-DC
   converter specification.
 - Intel SVID rev 1.9. protocol.
index 0e0eb2c8da7d541847ab2af34208f38c276898d5..6bc126a14b3d24cc9ba7f24a0975caecb1470153 100644 (file)
@@ -765,7 +765,7 @@ is not sufficient this sometimes needs to be explicit.
        Example::
 
                #arch/x86/boot/Makefile
-               subdir- := compressed/
+               subdir- := compressed
 
 The above assignment instructs kbuild to descend down in the
 directory compressed/ when "make clean" is executed.
@@ -1379,9 +1379,6 @@ See subsequent chapter for the syntax of the Kbuild file.
        in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate
        a wrapper of the asm-generic one.
 
-       The convention is to list one subdir per line and
-       preferably in alphabetic order.
-
 8 Kbuild Variables
 ==================
 
index 1e4735cc055351ff81bee0541dc221d974547bb1..256106054c8cb0b9d7fdc0a01f35100a388e6f08 100644 (file)
@@ -487,8 +487,9 @@ phy_register_fixup_for_id()::
 The stubs set one of the two matching criteria, and set the other one to
 match anything.
 
-When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module,
-unregister fixup and free allocate memory are required.
+When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load
+time, the module needs to unregister the fixup and free allocated memory when
+it's unloaded.
 
 Call one of following function before unloading module::
 
index 002e42745263a6416de98bb93532786ab444b5cf..ced8a80074348ec744d7bedff3ce681a0162d94b 100644 (file)
@@ -13,7 +13,6 @@ Power Management
     drivers-testing
     energy-model
     freezing-of-tasks
-    interface
     opp
     pci
     pm_qos_interface
index 33edae6545994830942c317a1aa2f8ee8666f407..a19d084f9b2cdefd2fd90810bb9b900b64c0f68b 100644 (file)
@@ -244,23 +244,23 @@ disclosure of a particular issue, unless requested by a response team or by
 an involved disclosed party. The current ambassadors list:
 
   ============= ========================================================
-  ARM
+  ARM           Grant Likely <grant.likely@arm.com>
   AMD          Tom Lendacky <tom.lendacky@amd.com>
   IBM
   Intel                Tony Luck <tony.luck@intel.com>
   Qualcomm     Trilok Soni <tsoni@codeaurora.org>
 
-  Microsoft    Sasha Levin <sashal@kernel.org>
+  Microsoft    James Morris <jamorris@linux.microsoft.com>
   VMware
   Xen          Andrew Cooper <andrew.cooper3@citrix.com>
 
-  Canonical    Tyler Hicks <tyhicks@canonical.com>
+  Canonical    John Johansen <john.johansen@canonical.com>
   Debian       Ben Hutchings <ben@decadent.org.uk>
   Oracle       Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
   SUSE         Jiri Kosina <jkosina@suse.cz>
 
-  Amazon       Peter Bowen <pzb@amzn.com>
+  Amazon
   Google       Kees Cook <keescook@chromium.org>
   ============= ========================================================
 
index 7daf5133bdd3144df4f9ae7c624effabaa9e3c01..e54c44ce117d51835f7aeaba820ca48256681915 100644 (file)
@@ -30,4 +30,4 @@ if [ -n "$parallel" ] ; then
        parallel="-j$parallel"
 fi
 
-exec "$sphinx" "$parallel" "$@"
+exec "$sphinx" $parallel "$@"
index b93f1af6826131fe9f1996f8ea1e8fa35d785871..88273ebe7823d4512fdd59e1823876cbfba0a66c 100644 (file)
@@ -183,7 +183,7 @@ CVE分配
   VMware
   Xen          Andrew Cooper <andrew.cooper3@citrix.com>
 
-  Canonical    Tyler Hicks <tyhicks@canonical.com>
+  Canonical    John Johansen <john.johansen@canonical.com>
   Debian       Ben Hutchings <ben@decadent.org.uk>
   Oracle       Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
index a9255002aa1c2e0ba1e0e66c026f7231ef8711f0..efbbe570aa9b7b3bf581e89e1508fb611294bf81 100644 (file)
@@ -4666,6 +4666,12 @@ KVM_PV_ENABLE
   command has succeeded, any CPU added via hotplug will become
   protected during its creation as well.
 
+  Errors:
+
+  =====      =============================
+  EINTR      an unmasked signal is pending
+  =====      =============================
+
 KVM_PV_DISABLE
 
   Deregister the VM from the Ultravisor and reclaim the memory that
index d1fc27d848e95d75ec5bada94d93f924fdf4c70c..d9eba93aa36426cb0746b234c183a070f3c95d48 100644 (file)
@@ -11,6 +11,11 @@ hypervisor when running as a guest (under Xen, KVM or any other
 hypervisor), or any hypervisor-specific interaction when the kernel is
 used as a host.
 
+Note: KVM/arm has been removed from the kernel. The API described
+here is still valid though, as it allows the kernel to kexec when
+booted at HYP. It can also be used by a hypervisor other than KVM
+if necessary.
+
 On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
 mode, but still needs to interact with it, allowing a built-in
 hypervisor to be either installed or torn down.
index a8de2fbc1caad73319ee40b2c16a2ec83642ea7e..265d9e9a093b8d3810b2148b3f794dfa58c0b473 100644 (file)
@@ -19,7 +19,6 @@ x86-specific Documentation
    tlb
    mtrr
    pat
-   intel_mpx
    intel-iommu
    intel_txt
    amd-memory-encryption
index 97a70647c93a9ef2561c7228a3001e77858c8cc2..d87d0093ed94b6bfec32b8dfb5bb9a51010ce038 100644 (file)
@@ -3649,6 +3649,7 @@ F:        sound/pci/oxygen/
 
 C-SKY ARCHITECTURE
 M:     Guo Ren <guoren@kernel.org>
+L:     linux-csky@vger.kernel.org
 T:     git https://github.com/c-sky/csky-linux.git
 S:     Supported
 F:     arch/csky/
@@ -3909,7 +3910,7 @@ S:        Supported
 F:     Documentation/filesystems/ceph.txt
 F:     fs/ceph/
 
-CERTIFICATE HANDLING:
+CERTIFICATE HANDLING
 M:     David Howells <dhowells@redhat.com>
 M:     David Woodhouse <dwmw2@infradead.org>
 L:     keyrings@vger.kernel.org
@@ -3919,7 +3920,7 @@ F:        certs/
 F:     scripts/sign-file.c
 F:     scripts/extract-cert.c
 
-CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
+CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM
 L:     devel@driverdev.osuosl.org
 S:     Obsolete
 F:     drivers/staging/wusbcore/
@@ -5932,12 +5933,12 @@ S:      Maintained
 F:     drivers/media/dvb-frontends/ec100*
 
 ECRYPT FILE SYSTEM
-M:     Tyler Hicks <tyhicks@canonical.com>
+M:     Tyler Hicks <code@tyhicks.com>
 L:     ecryptfs@vger.kernel.org
 W:     http://ecryptfs.org
 W:     https://launchpad.net/ecryptfs
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git
-S:     Supported
+S:     Odd Fixes
 F:     Documentation/filesystems/ecryptfs.txt
 F:     fs/ecryptfs/
 
@@ -7047,7 +7048,7 @@ L:        kvm@vger.kernel.org
 S:     Supported
 F:     drivers/uio/uio_pci_generic.c
 
-GENERIC VDSO LIBRARY:
+GENERIC VDSO LIBRARY
 M:     Andy Lutomirski <luto@kernel.org>
 M:     Thomas Gleixner <tglx@linutronix.de>
 M:     Vincenzo Frascino <vincenzo.frascino@arm.com>
@@ -8392,7 +8393,7 @@ M:        Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
 M:     Rodrigo Vivi <rodrigo.vivi@intel.com>
 L:     intel-gfx@lists.freedesktop.org
 W:     https://01.org/linuxgraphics/
-B:     https://01.org/linuxgraphics/documentation/how-report-bugs
+B:     https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 C:     irc://chat.freenode.net/intel-gfx
 Q:     http://patchwork.freedesktop.org/project/intel-gfx/
 T:     git git://anongit.freedesktop.org/drm-intel
@@ -9163,7 +9164,7 @@ F:        virt/kvm/*
 F:     tools/kvm/
 F:     tools/testing/selftests/kvm/
 
-KERNEL VIRTUAL MACHINE FOR ARM/ARM64 (KVM/arm, KVM/arm64)
+KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
 M:     Marc Zyngier <maz@kernel.org>
 R:     James Morse <james.morse@arm.com>
 R:     Julien Thierry <julien.thierry.kdev@gmail.com>
@@ -9172,9 +9173,6 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     kvmarm@lists.cs.columbia.edu
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git
 S:     Maintained
-F:     arch/arm/include/uapi/asm/kvm*
-F:     arch/arm/include/asm/kvm*
-F:     arch/arm/kvm/
 F:     arch/arm64/include/uapi/asm/kvm*
 F:     arch/arm64/include/asm/kvm*
 F:     arch/arm64/kvm/
@@ -9279,7 +9277,7 @@ F:        include/keys/trusted-type.h
 F:     security/keys/trusted.c
 F:     include/keys/trusted.h
 
-KEYS/KEYRINGS:
+KEYS/KEYRINGS
 M:     David Howells <dhowells@redhat.com>
 M:     Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
 L:     keyrings@vger.kernel.org
@@ -11115,14 +11113,12 @@ S:    Maintained
 F:     drivers/usb/image/microtek.*
 
 MIPS
-M:     Ralf Baechle <ralf@linux-mips.org>
-M:     Paul Burton <paulburton@kernel.org>
+M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
-S:     Supported
+S:     Maintained
 F:     Documentation/devicetree/bindings/mips/
 F:     Documentation/mips/
 F:     arch/mips/
@@ -11485,7 +11481,7 @@ F:      drivers/scsi/mac_scsi.*
 F:     drivers/scsi/sun3_scsi.*
 F:     drivers/scsi/sun3_scsi_vme.c
 
-NCSI LIBRARY:
+NCSI LIBRARY
 M:     Samuel Mendoza-Jonas <sam@mendozajonas.com>
 S:     Maintained
 F:     net/ncsi/
@@ -12741,7 +12737,7 @@ M:      Tom Joseph <tjoseph@cadence.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/cdns,*.txt
-F:     drivers/pci/controller/pcie-cadence*
+F:     drivers/pci/controller/cadence/
 
 PCI DRIVER FOR FREESCALE LAYERSCAPE
 M:     Minghuan Lian <minghuan.Lian@nxp.com>
@@ -13513,7 +13509,7 @@ L:      linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/block/ps3vram.c
 
-PSAMPLE PACKET SAMPLING SUPPORT:
+PSAMPLE PACKET SAMPLING SUPPORT
 M:     Yotam Gigi <yotam.gi@gmail.com>
 S:     Maintained
 F:     net/psample
@@ -14583,10 +14579,10 @@ F:    drivers/media/pci/saa7146/
 F:     include/media/drv-intf/saa7146*
 
 SAFESETID SECURITY MODULE
-M:     Micah Morton <mortonm@chromium.org>
-S:     Supported
-F:     security/safesetid/
-F:     Documentation/admin-guide/LSM/SafeSetID.rst
+M:     Micah Morton <mortonm@chromium.org>
+S:     Supported
+F:     security/safesetid/
+F:     Documentation/admin-guide/LSM/SafeSetID.rst
 
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
@@ -16553,8 +16549,8 @@ M:      Michael Jamet <michael.jamet@intel.com>
 M:     Mika Westerberg <mika.westerberg@linux.intel.com>
 M:     Yehezkel Bernat <YehezkelShB@gmail.com>
 L:     linux-usb@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
 F:     Documentation/admin-guide/thunderbolt.rst
 F:     drivers/thunderbolt/
 F:     include/linux/thunderbolt.h
@@ -17081,7 +17077,7 @@ S:      Maintained
 F:     Documentation/admin-guide/ufs.rst
 F:     fs/ufs/
 
-UHID USERSPACE HID IO DRIVER:
+UHID USERSPACE HID IO DRIVER
 M:     David Herrmann <dh.herrmann@googlemail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
@@ -17095,18 +17091,18 @@ S:    Maintained
 F:     drivers/usb/common/ulpi.c
 F:     include/linux/ulpi/
 
-ULTRA-WIDEBAND (UWB) SUBSYSTEM:
+ULTRA-WIDEBAND (UWB) SUBSYSTEM
 L:     devel@driverdev.osuosl.org
 S:     Obsolete
 F:     drivers/staging/uwb/
 
-UNICODE SUBSYSTEM:
+UNICODE SUBSYSTEM
 M:     Gabriel Krisman Bertazi <krisman@collabora.com>
 L:     linux-fsdevel@vger.kernel.org
 S:     Supported
 F:     fs/unicode/
 
-UNICORE32 ARCHITECTURE:
+UNICORE32 ARCHITECTURE
 M:     Guan Xuetao <gxt@pku.edu.cn>
 W:     http://mprc.pku.edu.cn/~guanxuetao/linux
 S:     Maintained
@@ -17393,11 +17389,14 @@ F:    drivers/usb/
 F:     include/linux/usb.h
 F:     include/linux/usb/
 
-USB TYPEC PI3USB30532 MUX DRIVER
-M:     Hans de Goede <hdegoede@redhat.com>
+USB TYPEC BUS FOR ALTERNATE MODES
+M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     drivers/usb/typec/mux/pi3usb30532.c
+F:     Documentation/ABI/testing/sysfs-bus-typec
+F:     Documentation/driver-api/usb/typec_bus.rst
+F:     drivers/usb/typec/altmodes/
+F:     include/linux/usb/typec_altmode.h
 
 USB TYPEC CLASS
 M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
@@ -17408,14 +17407,11 @@ F:    Documentation/driver-api/usb/typec.rst
 F:     drivers/usb/typec/
 F:     include/linux/usb/typec.h
 
-USB TYPEC BUS FOR ALTERNATE MODES
-M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
+USB TYPEC PI3USB30532 MUX DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-bus-typec
-F:     Documentation/driver-api/usb/typec_bus.rst
-F:     drivers/usb/typec/altmodes/
-F:     include/linux/usb/typec_altmode.h
+F:     drivers/usb/typec/mux/pi3usb30532.c
 
 USB TYPEC PORT CONTROLLER DRIVERS
 M:     Guenter Roeck <linux@roeck-us.net>
@@ -17792,7 +17788,7 @@ F:      include/linux/vbox_utils.h
 F:     include/uapi/linux/vbox*.h
 F:     drivers/virt/vboxguest/
 
-VIRTUAL BOX SHARED FOLDER VFS DRIVER:
+VIRTUAL BOX SHARED FOLDER VFS DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
index aab38cb02b249c03d5f3513574b32e439c123bf5..86035d866f2c0e73cf326980f0d9295173a73581 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -68,6 +68,7 @@ unexport GREP_OPTIONS
 #
 # If KBUILD_VERBOSE equals 0 then the above command will be hidden.
 # If KBUILD_VERBOSE equals 1 then the above command is displayed.
+# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
 #
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
@@ -1238,7 +1239,7 @@ ifneq ($(dtstree),)
 %.dtb: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
 
-PHONY += dtbs dtbs_install dt_binding_check
+PHONY += dtbs dtbs_install dtbs_check
 dtbs dtbs_check: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree)
 
@@ -1258,6 +1259,7 @@ PHONY += scripts_dtc
 scripts_dtc: scripts_basic
        $(Q)$(MAKE) $(build)=scripts/dtc
 
+PHONY += dt_binding_check
 dt_binding_check: scripts_dtc
        $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings
 
index 97864aabc2a6fa2aa7c86df3b19454b7e68c3dda..a07bec7f4d8ddc7557e199c22e75bc47f31dc3ac 100644 (file)
@@ -2091,5 +2091,3 @@ source "drivers/firmware/Kconfig"
 if CRYPTO
 source "arch/arm/crypto/Kconfig"
 endif
-
-source "arch/arm/kvm/Kconfig"
index db857d07114f18240ac7d2deec2710f7b838cf1a..b4ce96f55ddd301837e18fd4fc06fc5676609803 100644 (file)
@@ -278,7 +278,6 @@ core-$(CONFIG_FPE_NWFPE)    += arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)     += $(patsubst $(srctree)/%,%,$(wildcard $(srctree)/arch/arm/fastfpe/))
 core-$(CONFIG_VFP)             += arch/arm/vfp/
 core-$(CONFIG_XEN)             += arch/arm/xen/
-core-$(CONFIG_KVM_ARM_HOST)    += arch/arm/kvm/
 core-$(CONFIG_VDSO)            += arch/arm/vdso/
 
 # If we have a machine-specific directory, then include it in the build.
index 6ea7dafa4c9ea561826d2cd391d05ae823e451ee..46075216ee6df333ca1730566f9d406c65f7e7b3 100644 (file)
@@ -236,5 +236,3 @@ CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_SHA256=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_VIRTUALIZATION=y
-CONFIG_KVM=y
index c815477b4303ea52f487fd0737fb22cb187b4388..413abfb42989e9f3edc846aefc1ecef53a02daa1 100644 (file)
 #define ICC_AP1R2                      __ICC_AP1Rx(2)
 #define ICC_AP1R3                      __ICC_AP1Rx(3)
 
-#define ICC_HSRE                       __ACCESS_CP15(c12, 4, c9, 5)
-
-#define ICH_VSEIR                      __ACCESS_CP15(c12, 4, c9, 4)
-#define ICH_HCR                                __ACCESS_CP15(c12, 4, c11, 0)
-#define ICH_VTR                                __ACCESS_CP15(c12, 4, c11, 1)
-#define ICH_MISR                       __ACCESS_CP15(c12, 4, c11, 2)
-#define ICH_EISR                       __ACCESS_CP15(c12, 4, c11, 3)
-#define ICH_ELRSR                      __ACCESS_CP15(c12, 4, c11, 5)
-#define ICH_VMCR                       __ACCESS_CP15(c12, 4, c11, 7)
-
-#define __LR0(x)                       __ACCESS_CP15(c12, 4, c12, x)
-#define __LR8(x)                       __ACCESS_CP15(c12, 4, c13, x)
-
-#define ICH_LR0                                __LR0(0)
-#define ICH_LR1                                __LR0(1)
-#define ICH_LR2                                __LR0(2)
-#define ICH_LR3                                __LR0(3)
-#define ICH_LR4                                __LR0(4)
-#define ICH_LR5                                __LR0(5)
-#define ICH_LR6                                __LR0(6)
-#define ICH_LR7                                __LR0(7)
-#define ICH_LR8                                __LR8(0)
-#define ICH_LR9                                __LR8(1)
-#define ICH_LR10                       __LR8(2)
-#define ICH_LR11                       __LR8(3)
-#define ICH_LR12                       __LR8(4)
-#define ICH_LR13                       __LR8(5)
-#define ICH_LR14                       __LR8(6)
-#define ICH_LR15                       __LR8(7)
-
-/* LR top half */
-#define __LRC0(x)                      __ACCESS_CP15(c12, 4, c14, x)
-#define __LRC8(x)                      __ACCESS_CP15(c12, 4, c15, x)
-
-#define ICH_LRC0                       __LRC0(0)
-#define ICH_LRC1                       __LRC0(1)
-#define ICH_LRC2                       __LRC0(2)
-#define ICH_LRC3                       __LRC0(3)
-#define ICH_LRC4                       __LRC0(4)
-#define ICH_LRC5                       __LRC0(5)
-#define ICH_LRC6                       __LRC0(6)
-#define ICH_LRC7                       __LRC0(7)
-#define ICH_LRC8                       __LRC8(0)
-#define ICH_LRC9                       __LRC8(1)
-#define ICH_LRC10                      __LRC8(2)
-#define ICH_LRC11                      __LRC8(3)
-#define ICH_LRC12                      __LRC8(4)
-#define ICH_LRC13                      __LRC8(5)
-#define ICH_LRC14                      __LRC8(6)
-#define ICH_LRC15                      __LRC8(7)
-
-#define __ICH_AP0Rx(x)                 __ACCESS_CP15(c12, 4, c8, x)
-#define ICH_AP0R0                      __ICH_AP0Rx(0)
-#define ICH_AP0R1                      __ICH_AP0Rx(1)
-#define ICH_AP0R2                      __ICH_AP0Rx(2)
-#define ICH_AP0R3                      __ICH_AP0Rx(3)
-
-#define __ICH_AP1Rx(x)                 __ACCESS_CP15(c12, 4, c9, x)
-#define ICH_AP1R0                      __ICH_AP1Rx(0)
-#define ICH_AP1R1                      __ICH_AP1Rx(1)
-#define ICH_AP1R2                      __ICH_AP1Rx(2)
-#define ICH_AP1R3                      __ICH_AP1Rx(3)
-
-/* A32-to-A64 mappings used by VGIC save/restore */
-
 #define CPUIF_MAP(a32, a64)                    \
 static inline void write_ ## a64(u32 val)      \
 {                                              \
@@ -113,21 +48,6 @@ static inline u32 read_ ## a64(void)                \
        return read_sysreg(a32);                \
 }                                              \
 
-#define CPUIF_MAP_LO_HI(a32lo, a32hi, a64)     \
-static inline void write_ ## a64(u64 val)      \
-{                                              \
-       write_sysreg(lower_32_bits(val), a32lo);\
-       write_sysreg(upper_32_bits(val), a32hi);\
-}                                              \
-static inline u64 read_ ## a64(void)           \
-{                                              \
-       u64 val = read_sysreg(a32lo);           \
-                                               \
-       val |=  (u64)read_sysreg(a32hi) << 32;  \
-                                               \
-       return val;                             \
-}
-
 CPUIF_MAP(ICC_PMR, ICC_PMR_EL1)
 CPUIF_MAP(ICC_AP0R0, ICC_AP0R0_EL1)
 CPUIF_MAP(ICC_AP0R1, ICC_AP0R1_EL1)
@@ -138,40 +58,6 @@ CPUIF_MAP(ICC_AP1R1, ICC_AP1R1_EL1)
 CPUIF_MAP(ICC_AP1R2, ICC_AP1R2_EL1)
 CPUIF_MAP(ICC_AP1R3, ICC_AP1R3_EL1)
 
-CPUIF_MAP(ICH_HCR, ICH_HCR_EL2)
-CPUIF_MAP(ICH_VTR, ICH_VTR_EL2)
-CPUIF_MAP(ICH_MISR, ICH_MISR_EL2)
-CPUIF_MAP(ICH_EISR, ICH_EISR_EL2)
-CPUIF_MAP(ICH_ELRSR, ICH_ELRSR_EL2)
-CPUIF_MAP(ICH_VMCR, ICH_VMCR_EL2)
-CPUIF_MAP(ICH_AP0R3, ICH_AP0R3_EL2)
-CPUIF_MAP(ICH_AP0R2, ICH_AP0R2_EL2)
-CPUIF_MAP(ICH_AP0R1, ICH_AP0R1_EL2)
-CPUIF_MAP(ICH_AP0R0, ICH_AP0R0_EL2)
-CPUIF_MAP(ICH_AP1R3, ICH_AP1R3_EL2)
-CPUIF_MAP(ICH_AP1R2, ICH_AP1R2_EL2)
-CPUIF_MAP(ICH_AP1R1, ICH_AP1R1_EL2)
-CPUIF_MAP(ICH_AP1R0, ICH_AP1R0_EL2)
-CPUIF_MAP(ICC_HSRE, ICC_SRE_EL2)
-CPUIF_MAP(ICC_SRE, ICC_SRE_EL1)
-
-CPUIF_MAP_LO_HI(ICH_LR15, ICH_LRC15, ICH_LR15_EL2)
-CPUIF_MAP_LO_HI(ICH_LR14, ICH_LRC14, ICH_LR14_EL2)
-CPUIF_MAP_LO_HI(ICH_LR13, ICH_LRC13, ICH_LR13_EL2)
-CPUIF_MAP_LO_HI(ICH_LR12, ICH_LRC12, ICH_LR12_EL2)
-CPUIF_MAP_LO_HI(ICH_LR11, ICH_LRC11, ICH_LR11_EL2)
-CPUIF_MAP_LO_HI(ICH_LR10, ICH_LRC10, ICH_LR10_EL2)
-CPUIF_MAP_LO_HI(ICH_LR9, ICH_LRC9, ICH_LR9_EL2)
-CPUIF_MAP_LO_HI(ICH_LR8, ICH_LRC8, ICH_LR8_EL2)
-CPUIF_MAP_LO_HI(ICH_LR7, ICH_LRC7, ICH_LR7_EL2)
-CPUIF_MAP_LO_HI(ICH_LR6, ICH_LRC6, ICH_LR6_EL2)
-CPUIF_MAP_LO_HI(ICH_LR5, ICH_LRC5, ICH_LR5_EL2)
-CPUIF_MAP_LO_HI(ICH_LR4, ICH_LRC4, ICH_LR4_EL2)
-CPUIF_MAP_LO_HI(ICH_LR3, ICH_LRC3, ICH_LR3_EL2)
-CPUIF_MAP_LO_HI(ICH_LR2, ICH_LRC2, ICH_LR2_EL2)
-CPUIF_MAP_LO_HI(ICH_LR1, ICH_LRC1, ICH_LR1_EL2)
-CPUIF_MAP_LO_HI(ICH_LR0, ICH_LRC0, ICH_LR0_EL2)
-
 #define read_gicreg(r)                 read_##r()
 #define write_gicreg(v, r)             write_##r(v)
 
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
deleted file mode 100644 (file)
index 9c04bd8..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_ARM_H__
-#define __ARM_KVM_ARM_H__
-
-#include <linux/const.h>
-#include <linux/types.h>
-
-/* Hyp Configuration Register (HCR) bits */
-#define HCR_TGE                (1 << 27)
-#define HCR_TVM                (1 << 26)
-#define HCR_TTLB       (1 << 25)
-#define HCR_TPU                (1 << 24)
-#define HCR_TPC                (1 << 23)
-#define HCR_TSW                (1 << 22)
-#define HCR_TAC                (1 << 21)
-#define HCR_TIDCP      (1 << 20)
-#define HCR_TSC                (1 << 19)
-#define HCR_TID3       (1 << 18)
-#define HCR_TID2       (1 << 17)
-#define HCR_TID1       (1 << 16)
-#define HCR_TID0       (1 << 15)
-#define HCR_TWE                (1 << 14)
-#define HCR_TWI                (1 << 13)
-#define HCR_DC         (1 << 12)
-#define HCR_BSU                (3 << 10)
-#define HCR_BSU_IS     (1 << 10)
-#define HCR_FB         (1 << 9)
-#define HCR_VA         (1 << 8)
-#define HCR_VI         (1 << 7)
-#define HCR_VF         (1 << 6)
-#define HCR_AMO                (1 << 5)
-#define HCR_IMO                (1 << 4)
-#define HCR_FMO                (1 << 3)
-#define HCR_PTW                (1 << 2)
-#define HCR_SWIO       (1 << 1)
-#define HCR_VM         1
-
-/*
- * The bits we set in HCR:
- * TAC:                Trap ACTLR
- * TSC:                Trap SMC
- * TVM:                Trap VM ops (until MMU and caches are on)
- * TSW:                Trap cache operations by set/way
- * TWI:                Trap WFI
- * TWE:                Trap WFE
- * TIDCP:      Trap L2CTLR/L2ECTLR
- * BSU_IS:     Upgrade barriers to the inner shareable domain
- * FB:         Force broadcast of all maintainance operations
- * AMO:                Override CPSR.A and enable signaling with VA
- * IMO:                Override CPSR.I and enable signaling with VI
- * FMO:                Override CPSR.F and enable signaling with VF
- * SWIO:       Turn set/way invalidates into set/way clean+invalidate
- */
-#define HCR_GUEST_MASK (HCR_TSC | HCR_TSW | HCR_TWI | HCR_VM | HCR_BSU_IS | \
-                       HCR_FB | HCR_TAC | HCR_AMO | HCR_IMO | HCR_FMO | \
-                       HCR_TVM | HCR_TWE | HCR_SWIO | HCR_TIDCP)
-
-/* System Control Register (SCTLR) bits */
-#define SCTLR_TE       (1 << 30)
-#define SCTLR_EE       (1 << 25)
-#define SCTLR_V                (1 << 13)
-
-/* Hyp System Control Register (HSCTLR) bits */
-#define HSCTLR_TE      (1 << 30)
-#define HSCTLR_EE      (1 << 25)
-#define HSCTLR_FI      (1 << 21)
-#define HSCTLR_WXN     (1 << 19)
-#define HSCTLR_I       (1 << 12)
-#define HSCTLR_C       (1 << 2)
-#define HSCTLR_A       (1 << 1)
-#define HSCTLR_M       1
-#define HSCTLR_MASK    (HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I | \
-                        HSCTLR_WXN | HSCTLR_FI | HSCTLR_EE | HSCTLR_TE)
-
-/* TTBCR and HTCR Registers bits */
-#define TTBCR_EAE      (1 << 31)
-#define TTBCR_IMP      (1 << 30)
-#define TTBCR_SH1      (3 << 28)
-#define TTBCR_ORGN1    (3 << 26)
-#define TTBCR_IRGN1    (3 << 24)
-#define TTBCR_EPD1     (1 << 23)
-#define TTBCR_A1       (1 << 22)
-#define TTBCR_T1SZ     (7 << 16)
-#define TTBCR_SH0      (3 << 12)
-#define TTBCR_ORGN0    (3 << 10)
-#define TTBCR_IRGN0    (3 << 8)
-#define TTBCR_EPD0     (1 << 7)
-#define TTBCR_T0SZ     (7 << 0)
-#define HTCR_MASK      (TTBCR_T0SZ | TTBCR_IRGN0 | TTBCR_ORGN0 | TTBCR_SH0)
-
-/* Hyp System Trap Register */
-#define HSTR_T(x)      (1 << x)
-#define HSTR_TTEE      (1 << 16)
-#define HSTR_TJDBX     (1 << 17)
-
-/* Hyp Coprocessor Trap Register */
-#define HCPTR_TCP(x)   (1 << x)
-#define HCPTR_TCP_MASK (0x3fff)
-#define HCPTR_TASE     (1 << 15)
-#define HCPTR_TTA      (1 << 20)
-#define HCPTR_TCPAC    (1 << 31)
-
-/* Hyp Debug Configuration Register bits */
-#define HDCR_TDRA      (1 << 11)
-#define HDCR_TDOSA     (1 << 10)
-#define HDCR_TDA       (1 << 9)
-#define HDCR_TDE       (1 << 8)
-#define HDCR_HPME      (1 << 7)
-#define HDCR_TPM       (1 << 6)
-#define HDCR_TPMCR     (1 << 5)
-#define HDCR_HPMN_MASK (0x1F)
-
-/*
- * The architecture supports 40-bit IPA as input to the 2nd stage translations
- * and PTRS_PER_S2_PGD becomes 1024, because each entry covers 1GB of address
- * space.
- */
-#define KVM_PHYS_SHIFT (40)
-
-#define PTRS_PER_S2_PGD        (_AC(1, ULL) << (KVM_PHYS_SHIFT - 30))
-
-/* Virtualization Translation Control Register (VTCR) bits */
-#define VTCR_SH0       (3 << 12)
-#define VTCR_ORGN0     (3 << 10)
-#define VTCR_IRGN0     (3 << 8)
-#define VTCR_SL0       (3 << 6)
-#define VTCR_S         (1 << 4)
-#define VTCR_T0SZ      (0xf)
-#define VTCR_MASK      (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0 | VTCR_SL0 | \
-                        VTCR_S | VTCR_T0SZ)
-#define VTCR_HTCR_SH   (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0)
-#define VTCR_SL_L2     (0 << 6)        /* Starting-level: 2 */
-#define VTCR_SL_L1     (1 << 6)        /* Starting-level: 1 */
-#define KVM_VTCR_SL0   VTCR_SL_L1
-/* stage-2 input address range defined as 2^(32-T0SZ) */
-#define KVM_T0SZ       (32 - KVM_PHYS_SHIFT)
-#define KVM_VTCR_T0SZ  (KVM_T0SZ & VTCR_T0SZ)
-#define KVM_VTCR_S     ((KVM_VTCR_T0SZ << 1) & VTCR_S)
-
-/* Virtualization Translation Table Base Register (VTTBR) bits */
-#if KVM_VTCR_SL0 == VTCR_SL_L2 /* see ARM DDI 0406C: B4-1720 */
-#define VTTBR_X                (14 - KVM_T0SZ)
-#else
-#define VTTBR_X                (5 - KVM_T0SZ)
-#endif
-#define VTTBR_CNP_BIT     _AC(1, UL)
-#define VTTBR_BADDR_MASK  (((_AC(1, ULL) << (40 - VTTBR_X)) - 1) << VTTBR_X)
-#define VTTBR_VMID_SHIFT  _AC(48, ULL)
-#define VTTBR_VMID_MASK(size)  (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT)
-
-/* Hyp Syndrome Register (HSR) bits */
-#define HSR_EC_SHIFT   (26)
-#define HSR_EC         (_AC(0x3f, UL) << HSR_EC_SHIFT)
-#define HSR_IL         (_AC(1, UL) << 25)
-#define HSR_ISS                (HSR_IL - 1)
-#define HSR_ISV_SHIFT  (24)
-#define HSR_ISV                (_AC(1, UL) << HSR_ISV_SHIFT)
-#define HSR_SRT_SHIFT  (16)
-#define HSR_SRT_MASK   (0xf << HSR_SRT_SHIFT)
-#define HSR_CM         (1 << 8)
-#define HSR_FSC                (0x3f)
-#define HSR_FSC_TYPE   (0x3c)
-#define HSR_SSE                (1 << 21)
-#define HSR_WNR                (1 << 6)
-#define HSR_CV_SHIFT   (24)
-#define HSR_CV         (_AC(1, UL) << HSR_CV_SHIFT)
-#define HSR_COND_SHIFT (20)
-#define HSR_COND       (_AC(0xf, UL) << HSR_COND_SHIFT)
-
-#define FSC_FAULT      (0x04)
-#define FSC_ACCESS     (0x08)
-#define FSC_PERM       (0x0c)
-#define FSC_SEA                (0x10)
-#define FSC_SEA_TTW0   (0x14)
-#define FSC_SEA_TTW1   (0x15)
-#define FSC_SEA_TTW2   (0x16)
-#define FSC_SEA_TTW3   (0x17)
-#define FSC_SECC       (0x18)
-#define FSC_SECC_TTW0  (0x1c)
-#define FSC_SECC_TTW1  (0x1d)
-#define FSC_SECC_TTW2  (0x1e)
-#define FSC_SECC_TTW3  (0x1f)
-
-/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
-#define HPFAR_MASK     (~0xf)
-
-#define HSR_EC_UNKNOWN (0x00)
-#define HSR_EC_WFI     (0x01)
-#define HSR_EC_CP15_32 (0x03)
-#define HSR_EC_CP15_64 (0x04)
-#define HSR_EC_CP14_MR (0x05)
-#define HSR_EC_CP14_LS (0x06)
-#define HSR_EC_CP_0_13 (0x07)
-#define HSR_EC_CP10_ID (0x08)
-#define HSR_EC_JAZELLE (0x09)
-#define HSR_EC_BXJ     (0x0A)
-#define HSR_EC_CP14_64 (0x0C)
-#define HSR_EC_SVC_HYP (0x11)
-#define HSR_EC_HVC     (0x12)
-#define HSR_EC_SMC     (0x13)
-#define HSR_EC_IABT    (0x20)
-#define HSR_EC_IABT_HYP        (0x21)
-#define HSR_EC_DABT    (0x24)
-#define HSR_EC_DABT_HYP        (0x25)
-#define HSR_EC_MAX     (0x3f)
-
-#define HSR_WFI_IS_WFE         (_AC(1, UL) << 0)
-
-#define HSR_HVC_IMM_MASK       ((_AC(1, UL) << 16) - 1)
-
-#define HSR_DABT_S1PTW         (_AC(1, UL) << 7)
-#define HSR_DABT_CM            (_AC(1, UL) << 8)
-
-#define kvm_arm_exception_type \
-       {0, "RESET" },          \
-       {1, "UNDEFINED" },      \
-       {2, "SOFTWARE" },       \
-       {3, "PREF_ABORT" },     \
-       {4, "DATA_ABORT" },     \
-       {5, "IRQ" },            \
-       {6, "FIQ" },            \
-       {7, "HVC" }
-
-#define HSRECN(x) { HSR_EC_##x, #x }
-
-#define kvm_arm_exception_class \
-       HSRECN(UNKNOWN), HSRECN(WFI), HSRECN(CP15_32), HSRECN(CP15_64), \
-       HSRECN(CP14_MR), HSRECN(CP14_LS), HSRECN(CP_0_13), HSRECN(CP10_ID), \
-       HSRECN(JAZELLE), HSRECN(BXJ), HSRECN(CP14_64), HSRECN(SVC_HYP), \
-       HSRECN(HVC), HSRECN(SMC), HSRECN(IABT), HSRECN(IABT_HYP), \
-       HSRECN(DABT), HSRECN(DABT_HYP)
-
-
-#endif /* __ARM_KVM_ARM_H__ */
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
deleted file mode 100644 (file)
index f615830..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_ASM_H__
-#define __ARM_KVM_ASM_H__
-
-#include <asm/virt.h>
-
-#define ARM_EXIT_WITH_ABORT_BIT  31
-#define ARM_EXCEPTION_CODE(x)    ((x) & ~(1U << ARM_EXIT_WITH_ABORT_BIT))
-#define ARM_EXCEPTION_IS_TRAP(x)                                       \
-       (ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_PREF_ABORT    ||      \
-        ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_DATA_ABORT    ||      \
-        ARM_EXCEPTION_CODE((x)) == ARM_EXCEPTION_HVC)
-#define ARM_ABORT_PENDING(x)     !!((x) & (1U << ARM_EXIT_WITH_ABORT_BIT))
-
-#define ARM_EXCEPTION_RESET      0
-#define ARM_EXCEPTION_UNDEFINED   1
-#define ARM_EXCEPTION_SOFTWARE    2
-#define ARM_EXCEPTION_PREF_ABORT  3
-#define ARM_EXCEPTION_DATA_ABORT  4
-#define ARM_EXCEPTION_IRQ        5
-#define ARM_EXCEPTION_FIQ        6
-#define ARM_EXCEPTION_HVC        7
-#define ARM_EXCEPTION_HYP_GONE   HVC_STUB_ERR
-/*
- * The rr_lo_hi macro swaps a pair of registers depending on
- * current endianness. It is used in conjunction with ldrd and strd
- * instructions that load/store a 64-bit value from/to memory to/from
- * a pair of registers which are used with the mrrc and mcrr instructions.
- * If used with the ldrd/strd instructions, the a1 parameter is the first
- * source/destination register and the a2 parameter is the second
- * source/destination register. Note that the ldrd/strd instructions
- * already swap the bytes within the words correctly according to the
- * endianness setting, but the order of the registers need to be effectively
- * swapped when used with the mrrc/mcrr instructions.
- */
-#ifdef CONFIG_CPU_ENDIAN_BE8
-#define rr_lo_hi(a1, a2) a2, a1
-#else
-#define rr_lo_hi(a1, a2) a1, a2
-#endif
-
-#define kvm_ksym_ref(kva)      (kva)
-
-#ifndef __ASSEMBLY__
-struct kvm;
-struct kvm_vcpu;
-
-extern char __kvm_hyp_init[];
-extern char __kvm_hyp_init_end[];
-
-extern void __kvm_flush_vm_context(void);
-extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
-extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
-extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
-
-extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
-
-/* no VHE on 32-bit :( */
-static inline int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) { BUG(); return 0; }
-
-extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
-
-extern void __init_stage2_translation(void);
-
-extern u64 __vgic_v3_get_ich_vtr_el2(void);
-extern u64 __vgic_v3_read_vmcr(void);
-extern void __vgic_v3_write_vmcr(u32 vmcr);
-extern void __vgic_v3_init_lrs(void);
-
-#endif
-
-#endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
deleted file mode 100644 (file)
index a238261..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 Rusty Russell IBM Corporation
- */
-
-#ifndef __ARM_KVM_COPROC_H__
-#define __ARM_KVM_COPROC_H__
-#include <linux/kvm_host.h>
-
-void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
-
-struct kvm_coproc_target_table {
-       unsigned target;
-       const struct coproc_reg *table;
-       size_t num;
-};
-void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
-
-int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
-
-unsigned long kvm_arm_num_guest_msrs(struct kvm_vcpu *vcpu);
-int kvm_arm_copy_msrindices(struct kvm_vcpu *vcpu, u64 __user *uindices);
-void kvm_coproc_table_init(void);
-
-struct kvm_one_reg;
-int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
-int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
-int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
-unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
-#endif /* __ARM_KVM_COPROC_H__ */
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
deleted file mode 100644 (file)
index 3944305..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_EMULATE_H__
-#define __ARM_KVM_EMULATE_H__
-
-#include <linux/kvm_host.h>
-#include <asm/kvm_asm.h>
-#include <asm/kvm_arm.h>
-#include <asm/cputype.h>
-
-/* arm64 compatibility macros */
-#define PSR_AA32_MODE_FIQ      FIQ_MODE
-#define PSR_AA32_MODE_SVC      SVC_MODE
-#define PSR_AA32_MODE_ABT      ABT_MODE
-#define PSR_AA32_MODE_UND      UND_MODE
-#define PSR_AA32_T_BIT         PSR_T_BIT
-#define PSR_AA32_F_BIT         PSR_F_BIT
-#define PSR_AA32_I_BIT         PSR_I_BIT
-#define PSR_AA32_A_BIT         PSR_A_BIT
-#define PSR_AA32_E_BIT         PSR_E_BIT
-#define PSR_AA32_IT_MASK       PSR_IT_MASK
-#define PSR_AA32_GE_MASK       0x000f0000
-#define PSR_AA32_DIT_BIT       0x00200000
-#define PSR_AA32_PAN_BIT       0x00400000
-#define PSR_AA32_SSBS_BIT      0x00800000
-#define PSR_AA32_Q_BIT         PSR_Q_BIT
-#define PSR_AA32_V_BIT         PSR_V_BIT
-#define PSR_AA32_C_BIT         PSR_C_BIT
-#define PSR_AA32_Z_BIT         PSR_Z_BIT
-#define PSR_AA32_N_BIT         PSR_N_BIT
-
-unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
-
-static inline unsigned long *vcpu_reg32(struct kvm_vcpu *vcpu, u8 reg_num)
-{
-       return vcpu_reg(vcpu, reg_num);
-}
-
-unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu);
-
-static inline unsigned long vpcu_read_spsr(struct kvm_vcpu *vcpu)
-{
-       return *__vcpu_spsr(vcpu);
-}
-
-static inline void vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long v)
-{
-       *__vcpu_spsr(vcpu) = v;
-}
-
-static inline unsigned long host_spsr_to_spsr32(unsigned long spsr)
-{
-       return spsr;
-}
-
-static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
-                                        u8 reg_num)
-{
-       return *vcpu_reg(vcpu, reg_num);
-}
-
-static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
-                               unsigned long val)
-{
-       *vcpu_reg(vcpu, reg_num) = val;
-}
-
-bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
-void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
-void kvm_inject_undef32(struct kvm_vcpu *vcpu);
-void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
-void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
-void kvm_inject_vabt(struct kvm_vcpu *vcpu);
-
-static inline void kvm_inject_undefined(struct kvm_vcpu *vcpu)
-{
-       kvm_inject_undef32(vcpu);
-}
-
-static inline void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
-{
-       kvm_inject_dabt32(vcpu, addr);
-}
-
-static inline void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
-{
-       kvm_inject_pabt32(vcpu, addr);
-}
-
-static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
-{
-       return kvm_condition_valid32(vcpu);
-}
-
-static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
-{
-       kvm_skip_instr32(vcpu, is_wide_instr);
-}
-
-static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
-{
-       vcpu->arch.hcr = HCR_GUEST_MASK;
-}
-
-static inline unsigned long *vcpu_hcr(const struct kvm_vcpu *vcpu)
-{
-       return (unsigned long *)&vcpu->arch.hcr;
-}
-
-static inline void vcpu_clear_wfx_traps(struct kvm_vcpu *vcpu)
-{
-       vcpu->arch.hcr &= ~HCR_TWE;
-}
-
-static inline void vcpu_set_wfx_traps(struct kvm_vcpu *vcpu)
-{
-       vcpu->arch.hcr |= HCR_TWE;
-}
-
-static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
-{
-       return true;
-}
-
-static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
-{
-       return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_pc;
-}
-
-static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
-{
-       return (unsigned long *)&vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr;
-}
-
-static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
-{
-       *vcpu_cpsr(vcpu) |= PSR_T_BIT;
-}
-
-static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
-{
-       unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
-       return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
-}
-
-static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
-{
-       unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
-       return cpsr_mode > USR_MODE;
-}
-
-static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.fault.hsr;
-}
-
-static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
-{
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
-
-       if (hsr & HSR_CV)
-               return (hsr & HSR_COND) >> HSR_COND_SHIFT;
-
-       return -1;
-}
-
-static inline unsigned long kvm_vcpu_get_hfar(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.fault.hxfar;
-}
-
-static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
-{
-       return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
-}
-
-static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
-}
-
-static inline unsigned long kvm_vcpu_dabt_iss_nisv_sanitized(const struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & (HSR_CM | HSR_WNR | HSR_FSC);
-}
-
-static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
-}
-
-static inline bool kvm_vcpu_dabt_issext(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
-}
-
-static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
-{
-       return false;
-}
-
-static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
-{
-       return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
-}
-
-static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
-}
-
-static inline bool kvm_vcpu_dabt_is_cm(struct kvm_vcpu *vcpu)
-{
-       return !!(kvm_vcpu_get_hsr(vcpu) & HSR_DABT_CM);
-}
-
-/* Get Access Size from a data abort */
-static inline unsigned int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
-{
-       switch ((kvm_vcpu_get_hsr(vcpu) >> 22) & 0x3) {
-       case 0:
-               return 1;
-       case 1:
-               return 2;
-       case 2:
-               return 4;
-       default:
-               kvm_err("Hardware is weird: SAS 0b11 is reserved\n");
-               return 4;
-       }
-}
-
-/* This one is not specific to Data Abort */
-static inline bool kvm_vcpu_trap_il_is32bit(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
-}
-
-static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
-}
-
-static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
-}
-
-static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_FSC;
-}
-
-static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_FSC_TYPE;
-}
-
-static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu)
-{
-       switch (kvm_vcpu_trap_get_fault(vcpu)) {
-       case FSC_SEA:
-       case FSC_SEA_TTW0:
-       case FSC_SEA_TTW1:
-       case FSC_SEA_TTW2:
-       case FSC_SEA_TTW3:
-       case FSC_SECC:
-       case FSC_SECC_TTW0:
-       case FSC_SECC_TTW1:
-       case FSC_SECC_TTW2:
-       case FSC_SECC_TTW3:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
-{
-       if (kvm_vcpu_trap_is_iabt(vcpu))
-               return false;
-
-       return kvm_vcpu_dabt_iswrite(vcpu);
-}
-
-static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
-{
-       return kvm_vcpu_get_hsr(vcpu) & HSR_HVC_IMM_MASK;
-}
-
-static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
-{
-       return vcpu_cp15(vcpu, c0_MPIDR) & MPIDR_HWID_BITMASK;
-}
-
-static inline bool kvm_arm_get_vcpu_workaround_2_flag(struct kvm_vcpu *vcpu)
-{
-       return false;
-}
-
-static inline void kvm_arm_set_vcpu_workaround_2_flag(struct kvm_vcpu *vcpu,
-                                                     bool flag)
-{
-}
-
-static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
-{
-       *vcpu_cpsr(vcpu) |= PSR_E_BIT;
-}
-
-static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
-{
-       return !!(*vcpu_cpsr(vcpu) & PSR_E_BIT);
-}
-
-static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
-                                                   unsigned long data,
-                                                   unsigned int len)
-{
-       if (kvm_vcpu_is_be(vcpu)) {
-               switch (len) {
-               case 1:
-                       return data & 0xff;
-               case 2:
-                       return be16_to_cpu(data & 0xffff);
-               default:
-                       return be32_to_cpu(data);
-               }
-       } else {
-               switch (len) {
-               case 1:
-                       return data & 0xff;
-               case 2:
-                       return le16_to_cpu(data & 0xffff);
-               default:
-                       return le32_to_cpu(data);
-               }
-       }
-}
-
-static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
-                                                   unsigned long data,
-                                                   unsigned int len)
-{
-       if (kvm_vcpu_is_be(vcpu)) {
-               switch (len) {
-               case 1:
-                       return data & 0xff;
-               case 2:
-                       return cpu_to_be16(data & 0xffff);
-               default:
-                       return cpu_to_be32(data);
-               }
-       } else {
-               switch (len) {
-               case 1:
-                       return data & 0xff;
-               case 2:
-                       return cpu_to_le16(data & 0xffff);
-               default:
-                       return cpu_to_le32(data);
-               }
-       }
-}
-
-static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu) {}
-
-#endif /* __ARM_KVM_EMULATE_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
deleted file mode 100644 (file)
index c3314b2..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_HOST_H__
-#define __ARM_KVM_HOST_H__
-
-#include <linux/arm-smccc.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/kvm_types.h>
-#include <asm/cputype.h>
-#include <asm/kvm.h>
-#include <asm/kvm_asm.h>
-#include <asm/fpstate.h>
-#include <kvm/arm_arch_timer.h>
-
-#define __KVM_HAVE_ARCH_INTC_INITIALIZED
-
-#define KVM_USER_MEM_SLOTS 32
-#define KVM_HAVE_ONE_REG
-#define KVM_HALT_POLL_NS_DEFAULT 500000
-
-#define KVM_VCPU_MAX_FEATURES 2
-
-#include <kvm/arm_vgic.h>
-
-
-#ifdef CONFIG_ARM_GIC_V3
-#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
-#else
-#define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
-#endif
-
-#define KVM_REQ_SLEEP \
-       KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
-#define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
-#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
-#define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
-
-DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
-
-static inline int kvm_arm_init_sve(void) { return 0; }
-
-u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
-int __attribute_const__ kvm_target_cpu(void);
-int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
-void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
-
-struct kvm_vmid {
-       /* The VMID generation used for the virt. memory system */
-       u64    vmid_gen;
-       u32    vmid;
-};
-
-struct kvm_arch {
-       /* The last vcpu id that ran on each physical CPU */
-       int __percpu *last_vcpu_ran;
-
-       /*
-        * Anything that is not used directly from assembly code goes
-        * here.
-        */
-
-       /* The VMID generation used for the virt. memory system */
-       struct kvm_vmid vmid;
-
-       /* Stage-2 page table */
-       pgd_t *pgd;
-       phys_addr_t pgd_phys;
-
-       /* Interrupt controller */
-       struct vgic_dist        vgic;
-       int max_vcpus;
-
-       /* Mandated version of PSCI */
-       u32 psci_version;
-
-       /*
-        * If we encounter a data abort without valid instruction syndrome
-        * information, report this to user space.  User space can (and
-        * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
-        * supported.
-        */
-       bool return_nisv_io_abort_to_user;
-};
-
-#define KVM_NR_MEM_OBJS     40
-
-/*
- * We don't want allocation failures within the mmu code, so we preallocate
- * enough memory for a single page fault in a cache.
- */
-struct kvm_mmu_memory_cache {
-       int nobjs;
-       void *objects[KVM_NR_MEM_OBJS];
-};
-
-struct kvm_vcpu_fault_info {
-       u32 hsr;                /* Hyp Syndrome Register */
-       u32 hxfar;              /* Hyp Data/Inst. Fault Address Register */
-       u32 hpfar;              /* Hyp IPA Fault Address Register */
-};
-
-/*
- * 0 is reserved as an invalid value.
- * Order should be kept in sync with the save/restore code.
- */
-enum vcpu_sysreg {
-       __INVALID_SYSREG__,
-       c0_MPIDR,               /* MultiProcessor ID Register */
-       c0_CSSELR,              /* Cache Size Selection Register */
-       c1_SCTLR,               /* System Control Register */
-       c1_ACTLR,               /* Auxiliary Control Register */
-       c1_CPACR,               /* Coprocessor Access Control */
-       c2_TTBR0,               /* Translation Table Base Register 0 */
-       c2_TTBR0_high,          /* TTBR0 top 32 bits */
-       c2_TTBR1,               /* Translation Table Base Register 1 */
-       c2_TTBR1_high,          /* TTBR1 top 32 bits */
-       c2_TTBCR,               /* Translation Table Base Control R. */
-       c3_DACR,                /* Domain Access Control Register */
-       c5_DFSR,                /* Data Fault Status Register */
-       c5_IFSR,                /* Instruction Fault Status Register */
-       c5_ADFSR,               /* Auxilary Data Fault Status R */
-       c5_AIFSR,               /* Auxilary Instrunction Fault Status R */
-       c6_DFAR,                /* Data Fault Address Register */
-       c6_IFAR,                /* Instruction Fault Address Register */
-       c7_PAR,                 /* Physical Address Register */
-       c7_PAR_high,            /* PAR top 32 bits */
-       c9_L2CTLR,              /* Cortex A15/A7 L2 Control Register */
-       c10_PRRR,               /* Primary Region Remap Register */
-       c10_NMRR,               /* Normal Memory Remap Register */
-       c12_VBAR,               /* Vector Base Address Register */
-       c13_CID,                /* Context ID Register */
-       c13_TID_URW,            /* Thread ID, User R/W */
-       c13_TID_URO,            /* Thread ID, User R/O */
-       c13_TID_PRIV,           /* Thread ID, Privileged */
-       c14_CNTKCTL,            /* Timer Control Register (PL1) */
-       c10_AMAIR0,             /* Auxilary Memory Attribute Indirection Reg0 */
-       c10_AMAIR1,             /* Auxilary Memory Attribute Indirection Reg1 */
-       NR_CP15_REGS            /* Number of regs (incl. invalid) */
-};
-
-struct kvm_cpu_context {
-       struct kvm_regs gp_regs;
-       struct vfp_hard_struct vfp;
-       u32 cp15[NR_CP15_REGS];
-};
-
-struct kvm_host_data {
-       struct kvm_cpu_context host_ctxt;
-};
-
-typedef struct kvm_host_data kvm_host_data_t;
-
-static inline void kvm_init_host_cpu_context(struct kvm_cpu_context *cpu_ctxt)
-{
-       /* The host's MPIDR is immutable, so let's set it up at boot time */
-       cpu_ctxt->cp15[c0_MPIDR] = read_cpuid_mpidr();
-}
-
-struct vcpu_reset_state {
-       unsigned long   pc;
-       unsigned long   r0;
-       bool            be;
-       bool            reset;
-};
-
-struct kvm_vcpu_arch {
-       struct kvm_cpu_context ctxt;
-
-       int target; /* Processor target */
-       DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
-
-       /* The CPU type we expose to the VM */
-       u32 midr;
-
-       /* HYP trapping configuration */
-       u32 hcr;
-
-       /* Exception Information */
-       struct kvm_vcpu_fault_info fault;
-
-       /* Host FP context */
-       struct kvm_cpu_context *host_cpu_context;
-
-       /* VGIC state */
-       struct vgic_cpu vgic_cpu;
-       struct arch_timer_cpu timer_cpu;
-
-       /*
-        * Anything that is not used directly from assembly code goes
-        * here.
-        */
-
-       /* vcpu power-off state */
-       bool power_off;
-
-        /* Don't run the guest (internal implementation need) */
-       bool pause;
-
-       /* Cache some mmu pages needed inside spinlock regions */
-       struct kvm_mmu_memory_cache mmu_page_cache;
-
-       struct vcpu_reset_state reset_state;
-
-       /* Detect first run of a vcpu */
-       bool has_run_once;
-};
-
-struct kvm_vm_stat {
-       ulong remote_tlb_flush;
-};
-
-struct kvm_vcpu_stat {
-       u64 halt_successful_poll;
-       u64 halt_attempted_poll;
-       u64 halt_poll_invalid;
-       u64 halt_wakeup;
-       u64 hvc_exit_stat;
-       u64 wfe_exit_stat;
-       u64 wfi_exit_stat;
-       u64 mmio_exit_user;
-       u64 mmio_exit_kernel;
-       u64 exits;
-};
-
-#define vcpu_cp15(v,r) (v)->arch.ctxt.cp15[r]
-
-int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
-unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
-int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
-int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-
-unsigned long __kvm_call_hyp(void *hypfn, ...);
-
-/*
- * The has_vhe() part doesn't get emitted, but is used for type-checking.
- */
-#define kvm_call_hyp(f, ...)                                           \
-       do {                                                            \
-               if (has_vhe()) {                                        \
-                       f(__VA_ARGS__);                                 \
-               } else {                                                \
-                       __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__); \
-               }                                                       \
-       } while(0)
-
-#define kvm_call_hyp_ret(f, ...)                                       \
-       ({                                                              \
-               typeof(f(__VA_ARGS__)) ret;                             \
-                                                                       \
-               if (has_vhe()) {                                        \
-                       ret = f(__VA_ARGS__);                           \
-               } else {                                                \
-                       ret = __kvm_call_hyp(kvm_ksym_ref(f),           \
-                                            ##__VA_ARGS__);            \
-               }                                                       \
-                                                                       \
-               ret;                                                    \
-       })
-
-void force_vm_exit(const cpumask_t *mask);
-int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
-                             struct kvm_vcpu_events *events);
-
-int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
-                             struct kvm_vcpu_events *events);
-
-#define KVM_ARCH_WANT_MMU_NOTIFIER
-int kvm_unmap_hva_range(struct kvm *kvm,
-                       unsigned long start, unsigned long end);
-int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
-
-unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
-int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
-int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
-int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
-
-void kvm_arm_halt_guest(struct kvm *kvm);
-void kvm_arm_resume_guest(struct kvm *kvm);
-
-int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
-unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
-int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
-int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
-
-int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
-               int exception_index);
-
-static inline void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                                    int exception_index) {}
-
-/* MMIO helpers */
-void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
-unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
-
-int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                phys_addr_t fault_ipa);
-
-static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
-                                      unsigned long hyp_stack_ptr,
-                                      unsigned long vector_ptr)
-{
-       /*
-        * Call initialization code, and switch to the full blown HYP
-        * code. The init code doesn't need to preserve these
-        * registers as r0-r3 are already callee saved according to
-        * the AAPCS.
-        * Note that we slightly misuse the prototype by casting the
-        * stack pointer to a void *.
-
-        * The PGDs are always passed as the third argument, in order
-        * to be passed into r2-r3 to the init code (yes, this is
-        * compliant with the PCS!).
-        */
-
-       __kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
-}
-
-static inline void __cpu_init_stage2(void)
-{
-       kvm_call_hyp(__init_stage2_translation);
-}
-
-static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
-{
-       return 0;
-}
-
-int kvm_perf_init(void);
-int kvm_perf_teardown(void);
-
-static inline long kvm_hypercall_pv_features(struct kvm_vcpu *vcpu)
-{
-       return SMCCC_RET_NOT_SUPPORTED;
-}
-
-static inline gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
-{
-       return GPA_INVALID;
-}
-
-static inline void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
-{
-}
-
-static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
-{
-}
-
-static inline bool kvm_arm_is_pvtime_enabled(struct kvm_vcpu_arch *vcpu_arch)
-{
-       return false;
-}
-
-void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
-
-struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
-
-static inline bool kvm_arch_requires_vhe(void) { return false; }
-static inline void kvm_arch_hardware_unsetup(void) {}
-static inline void kvm_arch_sync_events(struct kvm *kvm) {}
-static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
-static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu) {}
-
-static inline void kvm_arm_init_debug(void) {}
-static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}
-
-int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr);
-int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr);
-int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr);
-
-/*
- * VFP/NEON switching is all done by the hyp switch code, so no need to
- * coordinate with host context handling for this state:
- */
-static inline void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
-
-static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
-static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
-
-static inline void kvm_arm_vhe_guest_enter(void) {}
-static inline void kvm_arm_vhe_guest_exit(void) {}
-
-#define KVM_BP_HARDEN_UNKNOWN          -1
-#define KVM_BP_HARDEN_WA_NEEDED                0
-#define KVM_BP_HARDEN_NOT_REQUIRED     1
-
-static inline int kvm_arm_harden_branch_predictor(void)
-{
-       switch(read_cpuid_part()) {
-#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
-       case ARM_CPU_PART_BRAHMA_B15:
-       case ARM_CPU_PART_CORTEX_A12:
-       case ARM_CPU_PART_CORTEX_A15:
-       case ARM_CPU_PART_CORTEX_A17:
-               return KVM_BP_HARDEN_WA_NEEDED;
-#endif
-       case ARM_CPU_PART_CORTEX_A7:
-               return KVM_BP_HARDEN_NOT_REQUIRED;
-       default:
-               return KVM_BP_HARDEN_UNKNOWN;
-       }
-}
-
-#define KVM_SSBD_UNKNOWN               -1
-#define KVM_SSBD_FORCE_DISABLE         0
-#define KVM_SSBD_KERNEL                1
-#define KVM_SSBD_FORCE_ENABLE          2
-#define KVM_SSBD_MITIGATED             3
-
-static inline int kvm_arm_have_ssbd(void)
-{
-       /* No way to detect it yet, pretend it is not there. */
-       return KVM_SSBD_UNKNOWN;
-}
-
-static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {}
-static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {}
-
-#define __KVM_HAVE_ARCH_VM_ALLOC
-struct kvm *kvm_arch_alloc_vm(void);
-void kvm_arch_free_vm(struct kvm *kvm);
-
-static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
-{
-       /*
-        * On 32bit ARM, VMs get a static 40bit IPA stage2 setup,
-        * so any non-zero value used as type is illegal.
-        */
-       if (type)
-               return -EINVAL;
-       return 0;
-}
-
-static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature)
-{
-       return -EINVAL;
-}
-
-static inline bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
-{
-       return true;
-}
-
-#endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
deleted file mode 100644 (file)
index 3c1b55e..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2015 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#ifndef __ARM_KVM_HYP_H__
-#define __ARM_KVM_HYP_H__
-
-#include <linux/compiler.h>
-#include <linux/kvm_host.h>
-#include <asm/cp15.h>
-#include <asm/kvm_arm.h>
-#include <asm/vfp.h>
-
-#define __hyp_text __section(.hyp.text) notrace
-
-#define __ACCESS_VFP(CRn)                      \
-       "mrc", "mcr", __stringify(p10, 7, %0, CRn, cr0, 0), u32
-
-#define write_special(v, r)                                    \
-       asm volatile("msr " __stringify(r) ", %0" : : "r" (v))
-#define read_special(r) ({                                     \
-       u32 __val;                                              \
-       asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
-       __val;                                                  \
-})
-
-#define TTBR0          __ACCESS_CP15_64(0, c2)
-#define TTBR1          __ACCESS_CP15_64(1, c2)
-#define VTTBR          __ACCESS_CP15_64(6, c2)
-#define PAR            __ACCESS_CP15_64(0, c7)
-#define CNTP_CVAL      __ACCESS_CP15_64(2, c14)
-#define CNTV_CVAL      __ACCESS_CP15_64(3, c14)
-#define CNTVOFF                __ACCESS_CP15_64(4, c14)
-
-#define MIDR           __ACCESS_CP15(c0, 0, c0, 0)
-#define CSSELR         __ACCESS_CP15(c0, 2, c0, 0)
-#define VPIDR          __ACCESS_CP15(c0, 4, c0, 0)
-#define VMPIDR         __ACCESS_CP15(c0, 4, c0, 5)
-#define SCTLR          __ACCESS_CP15(c1, 0, c0, 0)
-#define CPACR          __ACCESS_CP15(c1, 0, c0, 2)
-#define HCR            __ACCESS_CP15(c1, 4, c1, 0)
-#define HDCR           __ACCESS_CP15(c1, 4, c1, 1)
-#define HCPTR          __ACCESS_CP15(c1, 4, c1, 2)
-#define HSTR           __ACCESS_CP15(c1, 4, c1, 3)
-#define TTBCR          __ACCESS_CP15(c2, 0, c0, 2)
-#define HTCR           __ACCESS_CP15(c2, 4, c0, 2)
-#define VTCR           __ACCESS_CP15(c2, 4, c1, 2)
-#define DACR           __ACCESS_CP15(c3, 0, c0, 0)
-#define DFSR           __ACCESS_CP15(c5, 0, c0, 0)
-#define IFSR           __ACCESS_CP15(c5, 0, c0, 1)
-#define ADFSR          __ACCESS_CP15(c5, 0, c1, 0)
-#define AIFSR          __ACCESS_CP15(c5, 0, c1, 1)
-#define HSR            __ACCESS_CP15(c5, 4, c2, 0)
-#define DFAR           __ACCESS_CP15(c6, 0, c0, 0)
-#define IFAR           __ACCESS_CP15(c6, 0, c0, 2)
-#define HDFAR          __ACCESS_CP15(c6, 4, c0, 0)
-#define HIFAR          __ACCESS_CP15(c6, 4, c0, 2)
-#define HPFAR          __ACCESS_CP15(c6, 4, c0, 4)
-#define ICIALLUIS      __ACCESS_CP15(c7, 0, c1, 0)
-#define BPIALLIS       __ACCESS_CP15(c7, 0, c1, 6)
-#define ICIMVAU                __ACCESS_CP15(c7, 0, c5, 1)
-#define ATS1CPR                __ACCESS_CP15(c7, 0, c8, 0)
-#define TLBIALLIS      __ACCESS_CP15(c8, 0, c3, 0)
-#define TLBIALL                __ACCESS_CP15(c8, 0, c7, 0)
-#define TLBIALLNSNHIS  __ACCESS_CP15(c8, 4, c3, 4)
-#define PRRR           __ACCESS_CP15(c10, 0, c2, 0)
-#define NMRR           __ACCESS_CP15(c10, 0, c2, 1)
-#define AMAIR0         __ACCESS_CP15(c10, 0, c3, 0)
-#define AMAIR1         __ACCESS_CP15(c10, 0, c3, 1)
-#define VBAR           __ACCESS_CP15(c12, 0, c0, 0)
-#define CID            __ACCESS_CP15(c13, 0, c0, 1)
-#define TID_URW                __ACCESS_CP15(c13, 0, c0, 2)
-#define TID_URO                __ACCESS_CP15(c13, 0, c0, 3)
-#define TID_PRIV       __ACCESS_CP15(c13, 0, c0, 4)
-#define HTPIDR         __ACCESS_CP15(c13, 4, c0, 2)
-#define CNTKCTL                __ACCESS_CP15(c14, 0, c1, 0)
-#define CNTP_CTL       __ACCESS_CP15(c14, 0, c2, 1)
-#define CNTV_CTL       __ACCESS_CP15(c14, 0, c3, 1)
-#define CNTHCTL                __ACCESS_CP15(c14, 4, c1, 0)
-
-#define VFP_FPEXC      __ACCESS_VFP(FPEXC)
-
-/* AArch64 compatibility macros, only for the timer so far */
-#define read_sysreg_el0(r)             read_sysreg(r##_EL0)
-#define write_sysreg_el0(v, r)         write_sysreg(v, r##_EL0)
-
-#define SYS_CNTP_CTL_EL0               CNTP_CTL
-#define SYS_CNTP_CVAL_EL0              CNTP_CVAL
-#define SYS_CNTV_CTL_EL0               CNTV_CTL
-#define SYS_CNTV_CVAL_EL0              CNTV_CVAL
-
-#define cntvoff_el2                    CNTVOFF
-#define cnthctl_el2                    CNTHCTL
-
-void __timer_enable_traps(struct kvm_vcpu *vcpu);
-void __timer_disable_traps(struct kvm_vcpu *vcpu);
-
-void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
-void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
-
-void __sysreg_save_state(struct kvm_cpu_context *ctxt);
-void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
-
-void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
-void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
-void __vgic_v3_activate_traps(struct kvm_vcpu *vcpu);
-void __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu);
-void __vgic_v3_save_aprs(struct kvm_vcpu *vcpu);
-void __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu);
-
-asmlinkage void __vfp_save_state(struct vfp_hard_struct *vfp);
-asmlinkage void __vfp_restore_state(struct vfp_hard_struct *vfp);
-static inline bool __vfp_enabled(void)
-{
-       return !(read_sysreg(HCPTR) & (HCPTR_TCP(11) | HCPTR_TCP(10)));
-}
-
-void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt);
-void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt);
-
-asmlinkage int __guest_enter(struct kvm_vcpu *vcpu,
-                            struct kvm_cpu_context *host);
-asmlinkage int __hyp_do_panic(const char *, int, u32);
-
-#endif /* __ARM_KVM_HYP_H__ */
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
deleted file mode 100644 (file)
index 0d84d50..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_MMU_H__
-#define __ARM_KVM_MMU_H__
-
-#include <asm/memory.h>
-#include <asm/page.h>
-
-/*
- * We directly use the kernel VA for the HYP, as we can directly share
- * the mapping (HTTBR "covers" TTBR1).
- */
-#define kern_hyp_va(kva)       (kva)
-
-/* Contrary to arm64, there is no need to generate a PC-relative address */
-#define hyp_symbol_addr(s)                                             \
-       ({                                                              \
-               typeof(s) *addr = &(s);                                 \
-               addr;                                                   \
-       })
-
-#ifndef __ASSEMBLY__
-
-#include <linux/highmem.h>
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_hyp.h>
-#include <asm/pgalloc.h>
-#include <asm/stage2_pgtable.h>
-
-/* Ensure compatibility with arm64 */
-#define VA_BITS                        32
-
-#define kvm_phys_shift(kvm)            KVM_PHYS_SHIFT
-#define kvm_phys_size(kvm)             (1ULL << kvm_phys_shift(kvm))
-#define kvm_phys_mask(kvm)             (kvm_phys_size(kvm) - 1ULL)
-#define kvm_vttbr_baddr_mask(kvm)      VTTBR_BADDR_MASK
-
-#define stage2_pgd_size(kvm)           (PTRS_PER_S2_PGD * sizeof(pgd_t))
-
-int create_hyp_mappings(void *from, void *to, pgprot_t prot);
-int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
-                          void __iomem **kaddr,
-                          void __iomem **haddr);
-int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
-                            void **haddr);
-void free_hyp_pgds(void);
-
-void stage2_unmap_vm(struct kvm *kvm);
-int kvm_alloc_stage2_pgd(struct kvm *kvm);
-void kvm_free_stage2_pgd(struct kvm *kvm);
-int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
-                         phys_addr_t pa, unsigned long size, bool writable);
-
-int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run);
-
-void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
-
-phys_addr_t kvm_mmu_get_httbr(void);
-phys_addr_t kvm_get_idmap_vector(void);
-int kvm_mmu_init(void);
-void kvm_clear_hyp_idmap(void);
-
-#define kvm_mk_pmd(ptep)       __pmd(__pa(ptep) | PMD_TYPE_TABLE)
-#define kvm_mk_pud(pmdp)       __pud(__pa(pmdp) | PMD_TYPE_TABLE)
-#define kvm_mk_pgd(pudp)       ({ BUILD_BUG(); 0; })
-
-#define kvm_pfn_pte(pfn, prot) pfn_pte(pfn, prot)
-#define kvm_pfn_pmd(pfn, prot) pfn_pmd(pfn, prot)
-#define kvm_pfn_pud(pfn, prot) (__pud(0))
-
-#define kvm_pud_pfn(pud)       ({ WARN_ON(1); 0; })
-
-
-#define kvm_pmd_mkhuge(pmd)    pmd_mkhuge(pmd)
-/* No support for pud hugepages */
-#define kvm_pud_mkhuge(pud)    ( {WARN_ON(1); pud; })
-
-/*
- * The following kvm_*pud*() functions are provided strictly to allow
- * sharing code with arm64. They should never be called in practice.
- */
-static inline void kvm_set_s2pud_readonly(pud_t *pud)
-{
-       WARN_ON(1);
-}
-
-static inline bool kvm_s2pud_readonly(pud_t *pud)
-{
-       WARN_ON(1);
-       return false;
-}
-
-static inline void kvm_set_pud(pud_t *pud, pud_t new_pud)
-{
-       WARN_ON(1);
-}
-
-static inline pud_t kvm_s2pud_mkwrite(pud_t pud)
-{
-       WARN_ON(1);
-       return pud;
-}
-
-static inline pud_t kvm_s2pud_mkexec(pud_t pud)
-{
-       WARN_ON(1);
-       return pud;
-}
-
-static inline bool kvm_s2pud_exec(pud_t *pud)
-{
-       WARN_ON(1);
-       return false;
-}
-
-static inline pud_t kvm_s2pud_mkyoung(pud_t pud)
-{
-       BUG();
-       return pud;
-}
-
-static inline bool kvm_s2pud_young(pud_t pud)
-{
-       WARN_ON(1);
-       return false;
-}
-
-static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
-{
-       pte_val(pte) |= L_PTE_S2_RDWR;
-       return pte;
-}
-
-static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
-{
-       pmd_val(pmd) |= L_PMD_S2_RDWR;
-       return pmd;
-}
-
-static inline pte_t kvm_s2pte_mkexec(pte_t pte)
-{
-       pte_val(pte) &= ~L_PTE_XN;
-       return pte;
-}
-
-static inline pmd_t kvm_s2pmd_mkexec(pmd_t pmd)
-{
-       pmd_val(pmd) &= ~PMD_SECT_XN;
-       return pmd;
-}
-
-static inline void kvm_set_s2pte_readonly(pte_t *pte)
-{
-       pte_val(*pte) = (pte_val(*pte) & ~L_PTE_S2_RDWR) | L_PTE_S2_RDONLY;
-}
-
-static inline bool kvm_s2pte_readonly(pte_t *pte)
-{
-       return (pte_val(*pte) & L_PTE_S2_RDWR) == L_PTE_S2_RDONLY;
-}
-
-static inline bool kvm_s2pte_exec(pte_t *pte)
-{
-       return !(pte_val(*pte) & L_PTE_XN);
-}
-
-static inline void kvm_set_s2pmd_readonly(pmd_t *pmd)
-{
-       pmd_val(*pmd) = (pmd_val(*pmd) & ~L_PMD_S2_RDWR) | L_PMD_S2_RDONLY;
-}
-
-static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
-{
-       return (pmd_val(*pmd) & L_PMD_S2_RDWR) == L_PMD_S2_RDONLY;
-}
-
-static inline bool kvm_s2pmd_exec(pmd_t *pmd)
-{
-       return !(pmd_val(*pmd) & PMD_SECT_XN);
-}
-
-static inline bool kvm_page_empty(void *ptr)
-{
-       struct page *ptr_page = virt_to_page(ptr);
-       return page_count(ptr_page) == 1;
-}
-
-#define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
-#define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
-#define kvm_pud_table_empty(kvm, pudp) false
-
-#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
-#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
-#define hyp_pud_table_empty(pudp) false
-
-struct kvm;
-
-#define kvm_flush_dcache_to_poc(a,l)   __cpuc_flush_dcache_area((a), (l))
-
-static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
-{
-       return (vcpu_cp15(vcpu, c1_SCTLR) & 0b101) == 0b101;
-}
-
-static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
-{
-       /*
-        * Clean the dcache to the Point of Coherency.
-        *
-        * We need to do this through a kernel mapping (using the
-        * user-space mapping has proved to be the wrong
-        * solution). For that, we need to kmap one page at a time,
-        * and iterate over the range.
-        */
-
-       VM_BUG_ON(size & ~PAGE_MASK);
-
-       while (size) {
-               void *va = kmap_atomic_pfn(pfn);
-
-               kvm_flush_dcache_to_poc(va, PAGE_SIZE);
-
-               size -= PAGE_SIZE;
-               pfn++;
-
-               kunmap_atomic(va);
-       }
-}
-
-static inline void __invalidate_icache_guest_page(kvm_pfn_t pfn,
-                                                 unsigned long size)
-{
-       u32 iclsz;
-
-       /*
-        * If we are going to insert an instruction page and the icache is
-        * either VIPT or PIPT, there is a potential problem where the host
-        * (or another VM) may have used the same page as this guest, and we
-        * read incorrect data from the icache.  If we're using a PIPT cache,
-        * we can invalidate just that page, but if we are using a VIPT cache
-        * we need to invalidate the entire icache - damn shame - as written
-        * in the ARM ARM (DDI 0406C.b - Page B3-1393).
-        *
-        * VIVT caches are tagged using both the ASID and the VMID and doesn't
-        * need any kind of flushing (DDI 0406C.b - Page B3-1392).
-        */
-
-       VM_BUG_ON(size & ~PAGE_MASK);
-
-       if (icache_is_vivt_asid_tagged())
-               return;
-
-       if (!icache_is_pipt()) {
-               /* any kind of VIPT cache */
-               __flush_icache_all();
-               return;
-       }
-
-       /*
-        * CTR IminLine contains Log2 of the number of words in the
-        * cache line, so we can get the number of words as
-        * 2 << (IminLine - 1).  To get the number of bytes, we
-        * multiply by 4 (the number of bytes in a 32-bit word), and
-        * get 4 << (IminLine).
-        */
-       iclsz = 4 << (read_cpuid(CPUID_CACHETYPE) & 0xf);
-
-       while (size) {
-               void *va = kmap_atomic_pfn(pfn);
-               void *end = va + PAGE_SIZE;
-               void *addr = va;
-
-               do {
-                       write_sysreg(addr, ICIMVAU);
-                       addr += iclsz;
-               } while (addr < end);
-
-               dsb(ishst);
-               isb();
-
-               size -= PAGE_SIZE;
-               pfn++;
-
-               kunmap_atomic(va);
-       }
-
-       /* Check if we need to invalidate the BTB */
-       if ((read_cpuid_ext(CPUID_EXT_MMFR1) >> 28) != 4) {
-               write_sysreg(0, BPIALLIS);
-               dsb(ishst);
-               isb();
-       }
-}
-
-static inline void __kvm_flush_dcache_pte(pte_t pte)
-{
-       void *va = kmap_atomic(pte_page(pte));
-
-       kvm_flush_dcache_to_poc(va, PAGE_SIZE);
-
-       kunmap_atomic(va);
-}
-
-static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
-{
-       unsigned long size = PMD_SIZE;
-       kvm_pfn_t pfn = pmd_pfn(pmd);
-
-       while (size) {
-               void *va = kmap_atomic_pfn(pfn);
-
-               kvm_flush_dcache_to_poc(va, PAGE_SIZE);
-
-               pfn++;
-               size -= PAGE_SIZE;
-
-               kunmap_atomic(va);
-       }
-}
-
-static inline void __kvm_flush_dcache_pud(pud_t pud)
-{
-}
-
-#define kvm_virt_to_phys(x)            virt_to_idmap((unsigned long)(x))
-
-void kvm_set_way_flush(struct kvm_vcpu *vcpu);
-void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
-
-static inline bool __kvm_cpu_uses_extended_idmap(void)
-{
-       return false;
-}
-
-static inline unsigned long __kvm_idmap_ptrs_per_pgd(void)
-{
-       return PTRS_PER_PGD;
-}
-
-static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
-                                      pgd_t *hyp_pgd,
-                                      pgd_t *merged_hyp_pgd,
-                                      unsigned long hyp_idmap_start) { }
-
-static inline unsigned int kvm_get_vmid_bits(void)
-{
-       return 8;
-}
-
-/*
- * We are not in the kvm->srcu critical section most of the time, so we take
- * the SRCU read lock here. Since we copy the data from the user page, we
- * can immediately drop the lock again.
- */
-static inline int kvm_read_guest_lock(struct kvm *kvm,
-                                     gpa_t gpa, void *data, unsigned long len)
-{
-       int srcu_idx = srcu_read_lock(&kvm->srcu);
-       int ret = kvm_read_guest(kvm, gpa, data, len);
-
-       srcu_read_unlock(&kvm->srcu, srcu_idx);
-
-       return ret;
-}
-
-static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
-                                      const void *data, unsigned long len)
-{
-       int srcu_idx = srcu_read_lock(&kvm->srcu);
-       int ret = kvm_write_guest(kvm, gpa, data, len);
-
-       srcu_read_unlock(&kvm->srcu, srcu_idx);
-
-       return ret;
-}
-
-static inline void *kvm_get_hyp_vector(void)
-{
-       switch(read_cpuid_part()) {
-#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
-       case ARM_CPU_PART_CORTEX_A12:
-       case ARM_CPU_PART_CORTEX_A17:
-       {
-               extern char __kvm_hyp_vector_bp_inv[];
-               return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
-       }
-
-       case ARM_CPU_PART_BRAHMA_B15:
-       case ARM_CPU_PART_CORTEX_A15:
-       {
-               extern char __kvm_hyp_vector_ic_inv[];
-               return kvm_ksym_ref(__kvm_hyp_vector_ic_inv);
-       }
-#endif
-       default:
-       {
-               extern char __kvm_hyp_vector[];
-               return kvm_ksym_ref(__kvm_hyp_vector);
-       }
-       }
-}
-
-static inline int kvm_map_vectors(void)
-{
-       return 0;
-}
-
-static inline int hyp_map_aux_data(void)
-{
-       return 0;
-}
-
-#define kvm_phys_to_vttbr(addr)                (addr)
-
-static inline void kvm_set_ipa_limit(void) {}
-
-static __always_inline u64 kvm_get_vttbr(struct kvm *kvm)
-{
-       struct kvm_vmid *vmid = &kvm->arch.vmid;
-       u64 vmid_field, baddr;
-
-       baddr = kvm->arch.pgd_phys;
-       vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
-       return kvm_phys_to_vttbr(baddr) | vmid_field;
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/include/asm/kvm_ras.h b/arch/arm/include/asm/kvm_ras.h
deleted file mode 100644 (file)
index e957729..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (C) 2018 - Arm Ltd */
-
-#ifndef __ARM_KVM_RAS_H__
-#define __ARM_KVM_RAS_H__
-
-#include <linux/types.h>
-
-static inline int kvm_handle_guest_sea(phys_addr_t addr, unsigned int esr)
-{
-       return -1;
-}
-
-#endif /* __ARM_KVM_RAS_H__ */
index ad55ab068dbfe9c9e8b625c7dad5747b20c703fb..36805f94939eee75214195152e70d4108d436817 100644 (file)
  */
 #define L_PGD_SWAPPER          (_AT(pgdval_t, 1) << 55)        /* swapper_pg_dir entry */
 
-/*
- * 2nd stage PTE definitions for LPAE.
- */
-#define L_PTE_S2_MT_UNCACHED           (_AT(pteval_t, 0x0) << 2) /* strongly ordered */
-#define L_PTE_S2_MT_WRITETHROUGH       (_AT(pteval_t, 0xa) << 2) /* normal inner write-through */
-#define L_PTE_S2_MT_WRITEBACK          (_AT(pteval_t, 0xf) << 2) /* normal inner write-back */
-#define L_PTE_S2_MT_DEV_SHARED         (_AT(pteval_t, 0x1) << 2) /* device */
-#define L_PTE_S2_MT_MASK               (_AT(pteval_t, 0xf) << 2)
-
-#define L_PTE_S2_RDONLY                        (_AT(pteval_t, 1) << 6)   /* HAP[1]   */
-#define L_PTE_S2_RDWR                  (_AT(pteval_t, 3) << 6)   /* HAP[2:1] */
-
-#define L_PMD_S2_RDONLY                        (_AT(pmdval_t, 1) << 6)   /* HAP[1]   */
-#define L_PMD_S2_RDWR                  (_AT(pmdval_t, 3) << 6)   /* HAP[2:1] */
-
-/*
- * Hyp-mode PL2 PTE definitions for LPAE.
- */
-#define L_PTE_HYP              L_PTE_USER
-
 #ifndef __ASSEMBLY__
 
 #define pud_none(pud)          (!pud_val(pud))
index eabcb48a7840d3e53e03c4fe1dbd24ceb2f684c3..0483cf4133152fd1a3167ce3a122b8355c2690ad 100644 (file)
@@ -80,9 +80,6 @@ extern void __pgd_error(const char *file, int line, pgd_t);
 
 extern pgprot_t                pgprot_user;
 extern pgprot_t                pgprot_kernel;
-extern pgprot_t                pgprot_hyp_device;
-extern pgprot_t                pgprot_s2;
-extern pgprot_t                pgprot_s2_device;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
@@ -95,12 +92,6 @@ extern pgprot_t              pgprot_s2_device;
 #define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
 #define PAGE_KERNEL            _MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC       pgprot_kernel
-#define PAGE_HYP               _MOD_PROT(pgprot_kernel, L_PTE_HYP | L_PTE_XN)
-#define PAGE_HYP_EXEC          _MOD_PROT(pgprot_kernel, L_PTE_HYP | L_PTE_RDONLY)
-#define PAGE_HYP_RO            _MOD_PROT(pgprot_kernel, L_PTE_HYP | L_PTE_RDONLY | L_PTE_XN)
-#define PAGE_HYP_DEVICE                _MOD_PROT(pgprot_hyp_device, L_PTE_HYP)
-#define PAGE_S2                        _MOD_PROT(pgprot_s2, L_PTE_S2_RDONLY | L_PTE_XN)
-#define PAGE_S2_DEVICE         _MOD_PROT(pgprot_s2_device, L_PTE_S2_RDONLY | L_PTE_XN)
 
 #define __PAGE_NONE            __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN | L_PTE_NONE)
 #define __PAGE_SHARED          __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
index 4ceb4f757d4dc2c296b518ca570bc8e9fa9f9fd0..700b8bcdf9bdf121a34881508de0fbff8718bed4 100644 (file)
@@ -10,8 +10,6 @@ extern char __idmap_text_start[];
 extern char __idmap_text_end[];
 extern char __entry_text_start[];
 extern char __entry_text_end[];
-extern char __hyp_idmap_text_start[];
-extern char __hyp_idmap_text_end[];
 
 static inline bool in_entry_text(unsigned long addr)
 {
@@ -22,9 +20,7 @@ static inline bool in_entry_text(unsigned long addr)
 static inline bool in_idmap_text(unsigned long addr)
 {
        void *a = (void *)addr;
-       return memory_contains(__idmap_text_start, __idmap_text_end, a, 1) ||
-              memory_contains(__hyp_idmap_text_start, __hyp_idmap_text_end,
-                              a, 1);
+       return memory_contains(__idmap_text_start, __idmap_text_end, a, 1);
 }
 
 #endif /* _ASM_ARM_SECTIONS_H */
diff --git a/arch/arm/include/asm/stage2_pgtable.h b/arch/arm/include/asm/stage2_pgtable.h
deleted file mode 100644 (file)
index aaceec7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2016 - ARM Ltd
- *
- * stage2 page table helpers
- */
-
-#ifndef __ARM_S2_PGTABLE_H_
-#define __ARM_S2_PGTABLE_H_
-
-/*
- * kvm_mmu_cache_min_pages() is the number of pages required
- * to install a stage-2 translation. We pre-allocate the entry
- * level table at VM creation. Since we have a 3 level page-table,
- * we need only two pages to add a new mapping.
- */
-#define kvm_mmu_cache_min_pages(kvm)   2
-
-#define stage2_pgd_none(kvm, pgd)              pgd_none(pgd)
-#define stage2_pgd_clear(kvm, pgd)             pgd_clear(pgd)
-#define stage2_pgd_present(kvm, pgd)           pgd_present(pgd)
-#define stage2_pgd_populate(kvm, pgd, pud)     pgd_populate(NULL, pgd, pud)
-#define stage2_pud_offset(kvm, pgd, address)   pud_offset(pgd, address)
-#define stage2_pud_free(kvm, pud)              do { } while (0)
-
-#define stage2_pud_none(kvm, pud)              pud_none(pud)
-#define stage2_pud_clear(kvm, pud)             pud_clear(pud)
-#define stage2_pud_present(kvm, pud)           pud_present(pud)
-#define stage2_pud_populate(kvm, pud, pmd)     pud_populate(NULL, pud, pmd)
-#define stage2_pmd_offset(kvm, pud, address)   pmd_offset(pud, address)
-#define stage2_pmd_free(kvm, pmd)              free_page((unsigned long)pmd)
-
-#define stage2_pud_huge(kvm, pud)              pud_huge(pud)
-
-/* Open coded p*d_addr_end that can deal with 64bit addresses */
-static inline phys_addr_t
-stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
-{
-       phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK;
-
-       return (boundary - 1 < end - 1) ? boundary : end;
-}
-
-#define stage2_pud_addr_end(kvm, addr, end)    (end)
-
-static inline phys_addr_t
-stage2_pmd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
-{
-       phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK;
-
-       return (boundary - 1 < end - 1) ? boundary : end;
-}
-
-#define stage2_pgd_index(kvm, addr)            pgd_index(addr)
-
-#define stage2_pte_table_empty(kvm, ptep)      kvm_page_empty(ptep)
-#define stage2_pmd_table_empty(kvm, pmdp)      kvm_page_empty(pmdp)
-#define stage2_pud_table_empty(kvm, pudp)      false
-
-static inline bool kvm_stage2_has_pud(struct kvm *kvm)
-{
-       return false;
-}
-
-#define S2_PMD_MASK                            PMD_MASK
-#define S2_PMD_SIZE                            PMD_SIZE
-#define S2_PUD_MASK                            PUD_MASK
-#define S2_PUD_SIZE                            PUD_SIZE
-
-static inline bool kvm_stage2_has_pmd(struct kvm *kvm)
-{
-       return true;
-}
-
-#endif /* __ARM_S2_PGTABLE_H_ */
index 17c26ccd126d45088a602242496be0448558a770..dd9697b2bde8091aa5711f86db1d5130a570abb1 100644 (file)
@@ -39,8 +39,6 @@ static inline void sync_boot_mode(void)
        sync_cache_r(&__boot_cpu_mode);
 }
 
-void __hyp_set_vectors(unsigned long phys_vector_base);
-void __hyp_reset_vectors(void);
 #else
 #define __boot_cpu_mode        (SVC_MODE)
 #define sync_boot_mode()
@@ -67,18 +65,6 @@ static inline bool is_kernel_in_hyp_mode(void)
        return false;
 }
 
-static inline bool has_vhe(void)
-{
-       return false;
-}
-
-/* The section containing the hypervisor idmap text */
-extern char __hyp_idmap_text_start[];
-extern char __hyp_idmap_text_end[];
-
-/* The section containing the hypervisor text */
-extern char __hyp_text_start[];
-extern char __hyp_text_end[];
 #endif
 
 #else
@@ -87,9 +73,6 @@ extern char __hyp_text_end[];
 
 #define HVC_SET_VECTORS 0
 #define HVC_SOFT_RESTART 1
-#define HVC_RESET_VECTORS 2
-
-#define HVC_STUB_HCALL_NR 3
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
deleted file mode 100644 (file)
index 03cd7c1..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.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
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef __ARM_KVM_H__
-#define __ARM_KVM_H__
-
-#include <linux/types.h>
-#include <linux/psci.h>
-#include <asm/ptrace.h>
-
-#define __KVM_HAVE_GUEST_DEBUG
-#define __KVM_HAVE_IRQ_LINE
-#define __KVM_HAVE_READONLY_MEM
-#define __KVM_HAVE_VCPU_EVENTS
-
-#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
-
-#define KVM_REG_SIZE(id)                                               \
-       (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
-
-/* Valid for svc_regs, abt_regs, und_regs, irq_regs in struct kvm_regs */
-#define KVM_ARM_SVC_sp         svc_regs[0]
-#define KVM_ARM_SVC_lr         svc_regs[1]
-#define KVM_ARM_SVC_spsr       svc_regs[2]
-#define KVM_ARM_ABT_sp         abt_regs[0]
-#define KVM_ARM_ABT_lr         abt_regs[1]
-#define KVM_ARM_ABT_spsr       abt_regs[2]
-#define KVM_ARM_UND_sp         und_regs[0]
-#define KVM_ARM_UND_lr         und_regs[1]
-#define KVM_ARM_UND_spsr       und_regs[2]
-#define KVM_ARM_IRQ_sp         irq_regs[0]
-#define KVM_ARM_IRQ_lr         irq_regs[1]
-#define KVM_ARM_IRQ_spsr       irq_regs[2]
-
-/* Valid only for fiq_regs in struct kvm_regs */
-#define KVM_ARM_FIQ_r8         fiq_regs[0]
-#define KVM_ARM_FIQ_r9         fiq_regs[1]
-#define KVM_ARM_FIQ_r10                fiq_regs[2]
-#define KVM_ARM_FIQ_fp         fiq_regs[3]
-#define KVM_ARM_FIQ_ip         fiq_regs[4]
-#define KVM_ARM_FIQ_sp         fiq_regs[5]
-#define KVM_ARM_FIQ_lr         fiq_regs[6]
-#define KVM_ARM_FIQ_spsr       fiq_regs[7]
-
-struct kvm_regs {
-       struct pt_regs usr_regs;        /* R0_usr - R14_usr, PC, CPSR */
-       unsigned long svc_regs[3];      /* SP_svc, LR_svc, SPSR_svc */
-       unsigned long abt_regs[3];      /* SP_abt, LR_abt, SPSR_abt */
-       unsigned long und_regs[3];      /* SP_und, LR_und, SPSR_und */
-       unsigned long irq_regs[3];      /* SP_irq, LR_irq, SPSR_irq */
-       unsigned long fiq_regs[8];      /* R8_fiq - R14_fiq, SPSR_fiq */
-};
-
-/* Supported Processor Types */
-#define KVM_ARM_TARGET_CORTEX_A15      0
-#define KVM_ARM_TARGET_CORTEX_A7       1
-#define KVM_ARM_NUM_TARGETS            2
-
-/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
-#define KVM_ARM_DEVICE_TYPE_SHIFT      0
-#define KVM_ARM_DEVICE_TYPE_MASK       (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
-#define KVM_ARM_DEVICE_ID_SHIFT                16
-#define KVM_ARM_DEVICE_ID_MASK         (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
-
-/* Supported device IDs */
-#define KVM_ARM_DEVICE_VGIC_V2         0
-
-/* Supported VGIC address types  */
-#define KVM_VGIC_V2_ADDR_TYPE_DIST     0
-#define KVM_VGIC_V2_ADDR_TYPE_CPU      1
-
-#define KVM_VGIC_V2_DIST_SIZE          0x1000
-#define KVM_VGIC_V2_CPU_SIZE           0x2000
-
-/* Supported VGICv3 address types  */
-#define KVM_VGIC_V3_ADDR_TYPE_DIST     2
-#define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
-#define KVM_VGIC_ITS_ADDR_TYPE         4
-#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION    5
-
-#define KVM_VGIC_V3_DIST_SIZE          SZ_64K
-#define KVM_VGIC_V3_REDIST_SIZE                (2 * SZ_64K)
-#define KVM_VGIC_V3_ITS_SIZE           (2 * SZ_64K)
-
-#define KVM_ARM_VCPU_POWER_OFF         0 /* CPU is started in OFF state */
-#define KVM_ARM_VCPU_PSCI_0_2          1 /* CPU uses PSCI v0.2 */
-
-struct kvm_vcpu_init {
-       __u32 target;
-       __u32 features[7];
-};
-
-struct kvm_sregs {
-};
-
-struct kvm_fpu {
-};
-
-struct kvm_guest_debug_arch {
-};
-
-struct kvm_debug_exit_arch {
-};
-
-struct kvm_sync_regs {
-       /* Used with KVM_CAP_ARM_USER_IRQ */
-       __u64 device_irq_level;
-};
-
-struct kvm_arch_memory_slot {
-};
-
-/* for KVM_GET/SET_VCPU_EVENTS */
-struct kvm_vcpu_events {
-       struct {
-               __u8 serror_pending;
-               __u8 serror_has_esr;
-               __u8 ext_dabt_pending;
-               /* Align it to 8 bytes */
-               __u8 pad[5];
-               __u64 serror_esr;
-       } exception;
-       __u32 reserved[12];
-};
-
-/* If you need to interpret the index values, here is the key: */
-#define KVM_REG_ARM_COPROC_MASK                0x000000000FFF0000
-#define KVM_REG_ARM_COPROC_SHIFT       16
-#define KVM_REG_ARM_32_OPC2_MASK       0x0000000000000007
-#define KVM_REG_ARM_32_OPC2_SHIFT      0
-#define KVM_REG_ARM_OPC1_MASK          0x0000000000000078
-#define KVM_REG_ARM_OPC1_SHIFT         3
-#define KVM_REG_ARM_CRM_MASK           0x0000000000000780
-#define KVM_REG_ARM_CRM_SHIFT          7
-#define KVM_REG_ARM_32_CRN_MASK                0x0000000000007800
-#define KVM_REG_ARM_32_CRN_SHIFT       11
-/*
- * For KVM currently all guest registers are nonsecure, but we reserve a bit
- * in the encoding to distinguish secure from nonsecure for AArch32 system
- * registers that are banked by security. This is 1 for the secure banked
- * register, and 0 for the nonsecure banked register or if the register is
- * not banked by security.
- */
-#define KVM_REG_ARM_SECURE_MASK        0x0000000010000000
-#define KVM_REG_ARM_SECURE_SHIFT       28
-
-#define ARM_CP15_REG_SHIFT_MASK(x,n) \
-       (((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)
-
-#define __ARM_CP15_REG(op1,crn,crm,op2) \
-       (KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | \
-       ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
-       ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
-       ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
-       ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
-
-#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
-
-#define __ARM_CP15_REG64(op1,crm) \
-       (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
-#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
-
-/* PL1 Physical Timer Registers */
-#define KVM_REG_ARM_PTIMER_CTL         ARM_CP15_REG32(0, 14, 2, 1)
-#define KVM_REG_ARM_PTIMER_CNT         ARM_CP15_REG64(0, 14)
-#define KVM_REG_ARM_PTIMER_CVAL                ARM_CP15_REG64(2, 14)
-
-/* Virtual Timer Registers */
-#define KVM_REG_ARM_TIMER_CTL          ARM_CP15_REG32(0, 14, 3, 1)
-#define KVM_REG_ARM_TIMER_CNT          ARM_CP15_REG64(1, 14)
-#define KVM_REG_ARM_TIMER_CVAL         ARM_CP15_REG64(3, 14)
-
-/* Normal registers are mapped as coprocessor 16. */
-#define KVM_REG_ARM_CORE               (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_CORE_REG(name)     (offsetof(struct kvm_regs, name) / 4)
-
-/* Some registers need more space to represent values. */
-#define KVM_REG_ARM_DEMUX              (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_DEMUX_ID_MASK      0x000000000000FF00
-#define KVM_REG_ARM_DEMUX_ID_SHIFT     8
-#define KVM_REG_ARM_DEMUX_ID_CCSIDR    (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
-#define KVM_REG_ARM_DEMUX_VAL_MASK     0x00000000000000FF
-#define KVM_REG_ARM_DEMUX_VAL_SHIFT    0
-
-/* VFP registers: we could overload CP10 like ARM does, but that's ugly. */
-#define KVM_REG_ARM_VFP                        (0x0012 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_VFP_MASK           0x000000000000FFFF
-#define KVM_REG_ARM_VFP_BASE_REG       0x0
-#define KVM_REG_ARM_VFP_FPSID          0x1000
-#define KVM_REG_ARM_VFP_FPSCR          0x1001
-#define KVM_REG_ARM_VFP_MVFR1          0x1006
-#define KVM_REG_ARM_VFP_MVFR0          0x1007
-#define KVM_REG_ARM_VFP_FPEXC          0x1008
-#define KVM_REG_ARM_VFP_FPINST         0x1009
-#define KVM_REG_ARM_VFP_FPINST2                0x100A
-
-/* KVM-as-firmware specific pseudo-registers */
-#define KVM_REG_ARM_FW                 (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
-#define KVM_REG_ARM_FW_REG(r)          (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
-                                        KVM_REG_ARM_FW | ((r) & 0xffff))
-#define KVM_REG_ARM_PSCI_VERSION       KVM_REG_ARM_FW_REG(0)
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1    KVM_REG_ARM_FW_REG(1)
-       /* Higher values mean better protection. */
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL          0
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL              1
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED       2
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2    KVM_REG_ARM_FW_REG(2)
-       /* Higher values mean better protection. */
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL          0
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN            1
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL              2
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED       3
-#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED    (1U << 4)
-
-/* Device Control API: ARM VGIC */
-#define KVM_DEV_ARM_VGIC_GRP_ADDR      0
-#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
-#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
-#define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
-#define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
-#define   KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
-#define   KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
-                       (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
-#define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT        0
-#define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
-#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
-#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
-#define KVM_DEV_ARM_VGIC_GRP_CTRL       4
-#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
-#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
-#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
-#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS  8
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
-                       (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
-#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
-#define VGIC_LEVEL_INFO_LINE_LEVEL     0
-
-/* Device Control API on vcpu fd */
-#define KVM_ARM_VCPU_PMU_V3_CTRL       0
-#define   KVM_ARM_VCPU_PMU_V3_IRQ      0
-#define   KVM_ARM_VCPU_PMU_V3_INIT     1
-#define KVM_ARM_VCPU_TIMER_CTRL                1
-#define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER                0
-#define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER                1
-
-#define   KVM_DEV_ARM_VGIC_CTRL_INIT           0
-#define   KVM_DEV_ARM_ITS_SAVE_TABLES          1
-#define   KVM_DEV_ARM_ITS_RESTORE_TABLES       2
-#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
-#define   KVM_DEV_ARM_ITS_CTRL_RESET           4
-
-/* KVM_IRQ_LINE irq field index values */
-#define KVM_ARM_IRQ_VCPU2_SHIFT                28
-#define KVM_ARM_IRQ_VCPU2_MASK         0xf
-#define KVM_ARM_IRQ_TYPE_SHIFT         24
-#define KVM_ARM_IRQ_TYPE_MASK          0xf
-#define KVM_ARM_IRQ_VCPU_SHIFT         16
-#define KVM_ARM_IRQ_VCPU_MASK          0xff
-#define KVM_ARM_IRQ_NUM_SHIFT          0
-#define KVM_ARM_IRQ_NUM_MASK           0xffff
-
-/* irq_type field */
-#define KVM_ARM_IRQ_TYPE_CPU           0
-#define KVM_ARM_IRQ_TYPE_SPI           1
-#define KVM_ARM_IRQ_TYPE_PPI           2
-
-/* out-of-kernel GIC cpu interrupt injection irq_number field */
-#define KVM_ARM_IRQ_CPU_IRQ            0
-#define KVM_ARM_IRQ_CPU_FIQ            1
-
-/*
- * This used to hold the highest supported SPI, but it is now obsolete
- * and only here to provide source code level compatibility with older
- * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
- */
-#ifndef __KERNEL__
-#define KVM_ARM_IRQ_GIC_MAX            127
-#endif
-
-/* One single KVM irqchip, ie. the VGIC */
-#define KVM_NR_IRQCHIPS          1
-
-/* PSCI interface */
-#define KVM_PSCI_FN_BASE               0x95c1ba5e
-#define KVM_PSCI_FN(n)                 (KVM_PSCI_FN_BASE + (n))
-
-#define KVM_PSCI_FN_CPU_SUSPEND                KVM_PSCI_FN(0)
-#define KVM_PSCI_FN_CPU_OFF            KVM_PSCI_FN(1)
-#define KVM_PSCI_FN_CPU_ON             KVM_PSCI_FN(2)
-#define KVM_PSCI_FN_MIGRATE            KVM_PSCI_FN(3)
-
-#define KVM_PSCI_RET_SUCCESS           PSCI_RET_SUCCESS
-#define KVM_PSCI_RET_NI                        PSCI_RET_NOT_SUPPORTED
-#define KVM_PSCI_RET_INVAL             PSCI_RET_INVALID_PARAMS
-#define KVM_PSCI_RET_DENIED            PSCI_RET_DENIED
-
-#endif /* __ARM_KVM_H__ */
index c773b829ee8eefd303983fb90fad5d9ce8839a3d..c036a4a2f8e213fb650a1759781afa6cbba31005 100644 (file)
@@ -11,9 +11,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
-#ifdef CONFIG_KVM_ARM_HOST
-#include <linux/kvm_host.h>
-#endif
 #include <asm/cacheflush.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
@@ -167,14 +164,6 @@ int main(void)
   DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER);
   DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
   BLANK();
-#ifdef CONFIG_KVM_ARM_HOST
-  DEFINE(VCPU_GUEST_CTXT,      offsetof(struct kvm_vcpu, arch.ctxt));
-  DEFINE(VCPU_HOST_CTXT,       offsetof(struct kvm_vcpu, arch.host_cpu_context));
-  DEFINE(CPU_CTXT_VFP,         offsetof(struct kvm_cpu_context, vfp));
-  DEFINE(CPU_CTXT_GP_REGS,     offsetof(struct kvm_cpu_context, gp_regs));
-  DEFINE(GP_REGS_USR,          offsetof(struct kvm_regs, usr_regs));
-#endif
-  BLANK();
 #ifdef CONFIG_VDSO
   DEFINE(VDSO_DATA_SIZE,       sizeof(union vdso_data_store));
 #endif
index 6607fa817bba9a5510ac0a0c2de88342a80dfdb9..26d8e03b1dd336daecabcdba10480ffa83801d2a 100644 (file)
@@ -189,19 +189,19 @@ ARM_BE8(orr       r7, r7, #(1 << 25))     @ HSCTLR.EE
 ENDPROC(__hyp_stub_install_secondary)
 
 __hyp_stub_do_trap:
+#ifdef ZIMAGE
        teq     r0, #HVC_SET_VECTORS
        bne     1f
+       /* Only the ZIMAGE stubs can change the HYP vectors */
        mcr     p15, 4, r1, c12, c0, 0  @ set HVBAR
        b       __hyp_stub_exit
+#endif
 
 1:     teq     r0, #HVC_SOFT_RESTART
-       bne     1f
+       bne     2f
        bx      r1
 
-1:     teq     r0, #HVC_RESET_VECTORS
-       beq     __hyp_stub_exit
-
-       ldr     r0, =HVC_STUB_ERR
+2:     ldr     r0, =HVC_STUB_ERR
        __ERET
 
 __hyp_stub_exit:
@@ -210,26 +210,9 @@ __hyp_stub_exit:
 ENDPROC(__hyp_stub_do_trap)
 
 /*
- * __hyp_set_vectors: Call this after boot to set the initial hypervisor
- * vectors as part of hypervisor installation.  On an SMP system, this should
- * be called on each CPU.
- *
- * r0 must be the physical address of the new vector table (which must lie in
- * the bottom 4GB of physical address space.
- *
- * r0 must be 32-byte aligned.
- *
- * Before calling this, you must check that the stub hypervisor is installed
- * everywhere, by waiting for any secondary CPUs to be brought up and then
- * checking that BOOT_CPU_MODE_HAVE_HYP(__boot_cpu_mode) is true.
- *
- * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or
- * something else went wrong... in such cases, trying to install a new
- * hypervisor is unlikely to work as desired.
- *
- * When you call into your shiny new hypervisor, sp_hyp will contain junk,
- * so you will need to set that to something sensible at the new hypervisor's
- * initialisation entry point.
+ * __hyp_set_vectors is only used when ZIMAGE must bounce between HYP
+ * and SVC. For the kernel itself, the vectors are set once and for
+ * all by the stubs.
  */
 ENTRY(__hyp_set_vectors)
        mov     r1, r0
@@ -245,12 +228,6 @@ ENTRY(__hyp_soft_restart)
        ret     lr
 ENDPROC(__hyp_soft_restart)
 
-ENTRY(__hyp_reset_vectors)
-       mov     r0, #HVC_RESET_VECTORS
-       __HVC(0)
-       ret     lr
-ENDPROC(__hyp_reset_vectors)
-
 #ifndef ZIMAGE
 .align 2
 .L__boot_cpu_mode_offset:
index 21b8b271c80d2c469c99e6b909c175ab7e3b95db..6d2be994ae586f4a376c715a5b5d825618fc601a 100644 (file)
@@ -162,14 +162,6 @@ SECTIONS
 ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
 ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
 
-/*
- * The HYP init code can't be more than a page long,
- * and should not cross a page boundary.
- * The above comment applies as well.
- */
-ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
-       "HYP init code too big or misaligned")
-
 #ifdef CONFIG_XIP_DEFLATED_DATA
 /*
  * The .bss is used as a stack area for __inflate_kernel_data() whose stack
index 319ccb10846a6cae43883988e4c8776bbbc223ba..88a720da443b9815b8459dee496af2be69ecfa53 100644 (file)
@@ -170,12 +170,4 @@ __start_rodata_section_aligned = ALIGN(__start_rodata, 1 << SECTION_SHIFT);
 ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
 ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
 
-/*
- * The HYP init code can't be more than a page long,
- * and should not cross a page boundary.
- * The above comment applies as well.
- */
-ASSERT(__hyp_idmap_text_end - (__hyp_idmap_text_start & PAGE_MASK) <= PAGE_SIZE,
-       "HYP init code too big or misaligned")
-
 #endif /* CONFIG_XIP_KERNEL */
index 8247bc15addc419d2b6f4bf222d4f37e172ca0a7..381a8e105fa5389dad57f67cb787013a698c9db6 100644 (file)
                *(.proc.info.init)                                      \
                __proc_info_end = .;
 
-#define HYPERVISOR_TEXT                                                        \
-               __hyp_text_start = .;                                   \
-               *(.hyp.text)                                            \
-               __hyp_text_end = .;
-
 #define IDMAP_TEXT                                                     \
                ALIGN_FUNCTION();                                       \
                __idmap_text_start = .;                                 \
                *(.idmap.text)                                          \
                __idmap_text_end = .;                                   \
-               . = ALIGN(PAGE_SIZE);                                   \
-               __hyp_idmap_text_start = .;                             \
-               *(.hyp.idmap.text)                                      \
-               __hyp_idmap_text_end = .;
 
 #define ARM_DISCARD                                                    \
                *(.ARM.exidx.exit.text)                                 \
@@ -72,7 +63,6 @@
                SCHED_TEXT                                              \
                CPUIDLE_TEXT                                            \
                LOCK_TEXT                                               \
-               HYPERVISOR_TEXT                                         \
                KPROBES_TEXT                                            \
                *(.gnu.warning)                                         \
                *(.glue_7)                                              \
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
deleted file mode 100644 (file)
index f591026..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# KVM configuration
-#
-
-source "virt/kvm/Kconfig"
-source "virt/lib/Kconfig"
-
-menuconfig VIRTUALIZATION
-       bool "Virtualization"
-       ---help---
-         Say Y here to get to see options for using your Linux host to run
-         other operating systems inside virtual machines (guests).
-         This option alone does not add any kernel code.
-
-         If you say N, all options in this submenu will be skipped and
-         disabled.
-
-if VIRTUALIZATION
-
-config KVM
-       bool "Kernel-based Virtual Machine (KVM) support"
-       depends on MMU && OF
-       select PREEMPT_NOTIFIERS
-       select ARM_GIC
-       select ARM_GIC_V3
-       select ARM_GIC_V3_ITS
-       select HAVE_KVM_CPU_RELAX_INTERCEPT
-       select HAVE_KVM_ARCH_TLB_FLUSH_ALL
-       select KVM_MMIO
-       select KVM_ARM_HOST
-       select KVM_GENERIC_DIRTYLOG_READ_PROTECT
-       select SRCU
-       select MMU_NOTIFIER
-       select KVM_VFIO
-       select HAVE_KVM_EVENTFD
-       select HAVE_KVM_IRQFD
-       select HAVE_KVM_IRQCHIP
-       select HAVE_KVM_IRQ_ROUTING
-       select HAVE_KVM_MSI
-       select IRQ_BYPASS_MANAGER
-       select HAVE_KVM_IRQ_BYPASS
-       depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
-       ---help---
-         Support hosting virtualized guest machines.
-
-         This module provides access to the hardware capabilities through
-         a character device node named /dev/kvm.
-
-         If unsure, say N.
-
-config KVM_ARM_HOST
-       bool
-       ---help---
-         Provides host support for ARM processors.
-
-source "drivers/vhost/Kconfig"
-
-endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
deleted file mode 100644 (file)
index e442d82..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for Kernel-based Virtual Machine module
-#
-
-plus_virt := $(call as-instr,.arch_extension virt,+virt)
-ifeq ($(plus_virt),+virt)
-       plus_virt_def := -DREQUIRES_VIRT=1
-endif
-
-KVM := ../../../virt/kvm
-
-ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic
-CFLAGS_$(KVM)/arm/arm.o := $(plus_virt_def)
-
-AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
-AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
-
-kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
-
-obj-$(CONFIG_KVM_ARM_HOST) += hyp/
-
-obj-y += kvm-arm.o init.o interrupts.o
-obj-y += handle_exit.o guest.o emulate.o reset.o
-obj-y += coproc.o coproc_a15.o coproc_a7.o   vgic-v3-coproc.o
-obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
-obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o $(KVM)/arm/hypercalls.o
-obj-y += $(KVM)/arm/aarch32.o
-
-obj-y += $(KVM)/arm/vgic/vgic.o
-obj-y += $(KVM)/arm/vgic/vgic-init.o
-obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
-obj-y += $(KVM)/arm/vgic/vgic-v2.o
-obj-y += $(KVM)/arm/vgic/vgic-v3.o
-obj-y += $(KVM)/arm/vgic/vgic-v4.o
-obj-y += $(KVM)/arm/vgic/vgic-mmio.o
-obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
-obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
-obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
-obj-y += $(KVM)/arm/vgic/vgic-its.o
-obj-y += $(KVM)/arm/vgic/vgic-debug.o
-obj-y += $(KVM)/irqchip.o
-obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
deleted file mode 100644 (file)
index f0c0904..0000000
+++ /dev/null
@@ -1,1454 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Authors: Rusty Russell <rusty@rustcorp.com.au>
- *          Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/bsearch.h>
-#include <linux/mm.h>
-#include <linux/kvm_host.h>
-#include <linux/uaccess.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_emulate.h>
-#include <asm/kvm_coproc.h>
-#include <asm/kvm_mmu.h>
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <trace/events/kvm.h>
-#include <asm/vfp.h>
-#include "../vfp/vfpinstr.h"
-
-#define CREATE_TRACE_POINTS
-#include "trace.h"
-#include "coproc.h"
-
-
-/******************************************************************************
- * Co-processor emulation
- *****************************************************************************/
-
-static bool write_to_read_only(struct kvm_vcpu *vcpu,
-                              const struct coproc_params *params)
-{
-       WARN_ONCE(1, "CP15 write to read-only register\n");
-       print_cp_instr(params);
-       kvm_inject_undefined(vcpu);
-       return false;
-}
-
-static bool read_from_write_only(struct kvm_vcpu *vcpu,
-                                const struct coproc_params *params)
-{
-       WARN_ONCE(1, "CP15 read to write-only register\n");
-       print_cp_instr(params);
-       kvm_inject_undefined(vcpu);
-       return false;
-}
-
-/* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
-static u32 cache_levels;
-
-/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
-#define CSSELR_MAX 12
-
-/*
- * kvm_vcpu_arch.cp15 holds cp15 registers as an array of u32, but some
- * of cp15 registers can be viewed either as couple of two u32 registers
- * or one u64 register. Current u64 register encoding is that least
- * significant u32 word is followed by most significant u32 word.
- */
-static inline void vcpu_cp15_reg64_set(struct kvm_vcpu *vcpu,
-                                      const struct coproc_reg *r,
-                                      u64 val)
-{
-       vcpu_cp15(vcpu, r->reg) = val & 0xffffffff;
-       vcpu_cp15(vcpu, r->reg + 1) = val >> 32;
-}
-
-static inline u64 vcpu_cp15_reg64_get(struct kvm_vcpu *vcpu,
-                                     const struct coproc_reg *r)
-{
-       u64 val;
-
-       val = vcpu_cp15(vcpu, r->reg + 1);
-       val = val << 32;
-       val = val | vcpu_cp15(vcpu, r->reg);
-       return val;
-}
-
-int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
-int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       /*
-        * We can get here, if the host has been built without VFPv3 support,
-        * but the guest attempted a floating point operation.
-        */
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
-int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
-static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
-{
-       /*
-        * Compute guest MPIDR. We build a virtual cluster out of the
-        * vcpu_id, but we read the 'U' bit from the underlying
-        * hardware directly.
-        */
-       vcpu_cp15(vcpu, c0_MPIDR) = ((read_cpuid_mpidr() & MPIDR_SMP_BITMASK) |
-                                    ((vcpu->vcpu_id >> 2) << MPIDR_LEVEL_BITS) |
-                                    (vcpu->vcpu_id & 3));
-}
-
-/* TRM entries A7:4.3.31 A15:4.3.28 - RO WI */
-static bool access_actlr(struct kvm_vcpu *vcpu,
-                        const struct coproc_params *p,
-                        const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return ignore_write(vcpu, p);
-
-       *vcpu_reg(vcpu, p->Rt1) = vcpu_cp15(vcpu, c1_ACTLR);
-       return true;
-}
-
-/* TRM entries A7:4.3.56, A15:4.3.60 - R/O. */
-static bool access_cbar(struct kvm_vcpu *vcpu,
-                       const struct coproc_params *p,
-                       const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return write_to_read_only(vcpu, p);
-       return read_zero(vcpu, p);
-}
-
-/* TRM entries A7:4.3.49, A15:4.3.48 - R/O WI */
-static bool access_l2ctlr(struct kvm_vcpu *vcpu,
-                         const struct coproc_params *p,
-                         const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return ignore_write(vcpu, p);
-
-       *vcpu_reg(vcpu, p->Rt1) = vcpu_cp15(vcpu, c9_L2CTLR);
-       return true;
-}
-
-static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
-{
-       u32 l2ctlr, ncores;
-
-       asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
-       l2ctlr &= ~(3 << 24);
-       ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1;
-       /* How many cores in the current cluster and the next ones */
-       ncores -= (vcpu->vcpu_id & ~3);
-       /* Cap it to the maximum number of cores in a single cluster */
-       ncores = min(ncores, 3U);
-       l2ctlr |= (ncores & 3) << 24;
-
-       vcpu_cp15(vcpu, c9_L2CTLR) = l2ctlr;
-}
-
-static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
-{
-       u32 actlr;
-
-       /* ACTLR contains SMP bit: make sure you create all cpus first! */
-       asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr));
-       /* Make the SMP bit consistent with the guest configuration */
-       if (atomic_read(&vcpu->kvm->online_vcpus) > 1)
-               actlr |= 1U << 6;
-       else
-               actlr &= ~(1U << 6);
-
-       vcpu_cp15(vcpu, c1_ACTLR) = actlr;
-}
-
-/*
- * TRM entries: A7:4.3.50, A15:4.3.49
- * R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored).
- */
-static bool access_l2ectlr(struct kvm_vcpu *vcpu,
-                          const struct coproc_params *p,
-                          const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return ignore_write(vcpu, p);
-
-       *vcpu_reg(vcpu, p->Rt1) = 0;
-       return true;
-}
-
-/*
- * See note at ARMv7 ARM B1.14.4 (TL;DR: S/W ops are not easily virtualized).
- */
-static bool access_dcsw(struct kvm_vcpu *vcpu,
-                       const struct coproc_params *p,
-                       const struct coproc_reg *r)
-{
-       if (!p->is_write)
-               return read_from_write_only(vcpu, p);
-
-       kvm_set_way_flush(vcpu);
-       return true;
-}
-
-/*
- * Generic accessor for VM registers. Only called as long as HCR_TVM
- * is set.  If the guest enables the MMU, we stop trapping the VM
- * sys_regs and leave it in complete control of the caches.
- *
- * Used by the cpu-specific code.
- */
-bool access_vm_reg(struct kvm_vcpu *vcpu,
-                  const struct coproc_params *p,
-                  const struct coproc_reg *r)
-{
-       bool was_enabled = vcpu_has_cache_enabled(vcpu);
-
-       BUG_ON(!p->is_write);
-
-       vcpu_cp15(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt1);
-       if (p->is_64bit)
-               vcpu_cp15(vcpu, r->reg + 1) = *vcpu_reg(vcpu, p->Rt2);
-
-       kvm_toggle_cache(vcpu, was_enabled);
-       return true;
-}
-
-static bool access_gic_sgi(struct kvm_vcpu *vcpu,
-                          const struct coproc_params *p,
-                          const struct coproc_reg *r)
-{
-       u64 reg;
-       bool g1;
-
-       if (!p->is_write)
-               return read_from_write_only(vcpu, p);
-
-       reg = (u64)*vcpu_reg(vcpu, p->Rt2) << 32;
-       reg |= *vcpu_reg(vcpu, p->Rt1) ;
-
-       /*
-        * In a system where GICD_CTLR.DS=1, a ICC_SGI0R access generates
-        * Group0 SGIs only, while ICC_SGI1R can generate either group,
-        * depending on the SGI configuration. ICC_ASGI1R is effectively
-        * equivalent to ICC_SGI0R, as there is no "alternative" secure
-        * group.
-        */
-       switch (p->Op1) {
-       default:                /* Keep GCC quiet */
-       case 0:                 /* ICC_SGI1R */
-               g1 = true;
-               break;
-       case 1:                 /* ICC_ASGI1R */
-       case 2:                 /* ICC_SGI0R */
-               g1 = false;
-               break;
-       }
-
-       vgic_v3_dispatch_sgi(vcpu, reg, g1);
-
-       return true;
-}
-
-static bool access_gic_sre(struct kvm_vcpu *vcpu,
-                          const struct coproc_params *p,
-                          const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return ignore_write(vcpu, p);
-
-       *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
-
-       return true;
-}
-
-static bool access_cntp_tval(struct kvm_vcpu *vcpu,
-                            const struct coproc_params *p,
-                            const struct coproc_reg *r)
-{
-       u32 val;
-
-       if (p->is_write) {
-               val = *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_write_sysreg(vcpu,
-                                          TIMER_PTIMER, TIMER_REG_TVAL, val);
-       } else {
-               val = kvm_arm_timer_read_sysreg(vcpu,
-                                               TIMER_PTIMER, TIMER_REG_TVAL);
-               *vcpu_reg(vcpu, p->Rt1) = val;
-       }
-
-       return true;
-}
-
-static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
-                           const struct coproc_params *p,
-                           const struct coproc_reg *r)
-{
-       u32 val;
-
-       if (p->is_write) {
-               val = *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_write_sysreg(vcpu,
-                                          TIMER_PTIMER, TIMER_REG_CTL, val);
-       } else {
-               val = kvm_arm_timer_read_sysreg(vcpu,
-                                               TIMER_PTIMER, TIMER_REG_CTL);
-               *vcpu_reg(vcpu, p->Rt1) = val;
-       }
-
-       return true;
-}
-
-static bool access_cntp_cval(struct kvm_vcpu *vcpu,
-                            const struct coproc_params *p,
-                            const struct coproc_reg *r)
-{
-       u64 val;
-
-       if (p->is_write) {
-               val = (u64)*vcpu_reg(vcpu, p->Rt2) << 32;
-               val |= *vcpu_reg(vcpu, p->Rt1);
-               kvm_arm_timer_write_sysreg(vcpu,
-                                          TIMER_PTIMER, TIMER_REG_CVAL, val);
-       } else {
-               val = kvm_arm_timer_read_sysreg(vcpu,
-                                               TIMER_PTIMER, TIMER_REG_CVAL);
-               *vcpu_reg(vcpu, p->Rt1) = val;
-               *vcpu_reg(vcpu, p->Rt2) = val >> 32;
-       }
-
-       return true;
-}
-
-/*
- * We could trap ID_DFR0 and tell the guest we don't support performance
- * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
- * NAKed, so it will read the PMCR anyway.
- *
- * Therefore we tell the guest we have 0 counters.  Unfortunately, we
- * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
- * all PM registers, which doesn't crash the guest kernel at least.
- */
-static bool trap_raz_wi(struct kvm_vcpu *vcpu,
-                   const struct coproc_params *p,
-                   const struct coproc_reg *r)
-{
-       if (p->is_write)
-               return ignore_write(vcpu, p);
-       else
-               return read_zero(vcpu, p);
-}
-
-#define access_pmcr trap_raz_wi
-#define access_pmcntenset trap_raz_wi
-#define access_pmcntenclr trap_raz_wi
-#define access_pmovsr trap_raz_wi
-#define access_pmselr trap_raz_wi
-#define access_pmceid0 trap_raz_wi
-#define access_pmceid1 trap_raz_wi
-#define access_pmccntr trap_raz_wi
-#define access_pmxevtyper trap_raz_wi
-#define access_pmxevcntr trap_raz_wi
-#define access_pmuserenr trap_raz_wi
-#define access_pmintenset trap_raz_wi
-#define access_pmintenclr trap_raz_wi
-
-/* Architected CP15 registers.
- * CRn denotes the primary register number, but is copied to the CRm in the
- * user space API for 64-bit register access in line with the terminology used
- * in the ARM ARM.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
- *            registers preceding 32-bit ones.
- */
-static const struct coproc_reg cp15_regs[] = {
-       /* MPIDR: we use VMPIDR for guest access. */
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 5), is32,
-                       NULL, reset_mpidr, c0_MPIDR },
-
-       /* CSSELR: swapped by interrupt.S. */
-       { CRn( 0), CRm( 0), Op1( 2), Op2( 0), is32,
-                       NULL, reset_unknown, c0_CSSELR },
-
-       /* ACTLR: trapped by HCR.TAC bit. */
-       { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32,
-                       access_actlr, reset_actlr, c1_ACTLR },
-
-       /* CPACR: swapped by interrupt.S. */
-       { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32,
-                       NULL, reset_val, c1_CPACR, 0x00000000 },
-
-       /* TTBR0/TTBR1/TTBCR: swapped by interrupt.S. */
-       { CRm64( 2), Op1( 0), is64, access_vm_reg, reset_unknown64, c2_TTBR0 },
-       { CRn(2), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c2_TTBR0 },
-       { CRn(2), CRm( 0), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_unknown, c2_TTBR1 },
-       { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
-                       access_vm_reg, reset_val, c2_TTBCR, 0x00000000 },
-       { CRm64( 2), Op1( 1), is64, access_vm_reg, reset_unknown64, c2_TTBR1 },
-
-
-       /* DACR: swapped by interrupt.S. */
-       { CRn( 3), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c3_DACR },
-
-       /* DFSR/IFSR/ADFSR/AIFSR: swapped by interrupt.S. */
-       { CRn( 5), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c5_DFSR },
-       { CRn( 5), CRm( 0), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_unknown, c5_IFSR },
-       { CRn( 5), CRm( 1), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c5_ADFSR },
-       { CRn( 5), CRm( 1), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_unknown, c5_AIFSR },
-
-       /* DFAR/IFAR: swapped by interrupt.S. */
-       { CRn( 6), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c6_DFAR },
-       { CRn( 6), CRm( 0), Op1( 0), Op2( 2), is32,
-                       access_vm_reg, reset_unknown, c6_IFAR },
-
-       /* PAR swapped by interrupt.S */
-       { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
-
-       /*
-        * DC{C,I,CI}SW operations:
-        */
-       { CRn( 7), CRm( 6), Op1( 0), Op2( 2), is32, access_dcsw},
-       { CRn( 7), CRm(10), Op1( 0), Op2( 2), is32, access_dcsw},
-       { CRn( 7), CRm(14), Op1( 0), Op2( 2), is32, access_dcsw},
-       /*
-        * L2CTLR access (guest wants to know #CPUs).
-        */
-       { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32,
-                       access_l2ctlr, reset_l2ctlr, c9_L2CTLR },
-       { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr},
-
-       /*
-        * Dummy performance monitor implementation.
-        */
-       { CRn( 9), CRm(12), Op1( 0), Op2( 0), is32, access_pmcr},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 1), is32, access_pmcntenset},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 2), is32, access_pmcntenclr},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 3), is32, access_pmovsr},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 5), is32, access_pmselr},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 6), is32, access_pmceid0},
-       { CRn( 9), CRm(12), Op1( 0), Op2( 7), is32, access_pmceid1},
-       { CRn( 9), CRm(13), Op1( 0), Op2( 0), is32, access_pmccntr},
-       { CRn( 9), CRm(13), Op1( 0), Op2( 1), is32, access_pmxevtyper},
-       { CRn( 9), CRm(13), Op1( 0), Op2( 2), is32, access_pmxevcntr},
-       { CRn( 9), CRm(14), Op1( 0), Op2( 0), is32, access_pmuserenr},
-       { CRn( 9), CRm(14), Op1( 0), Op2( 1), is32, access_pmintenset},
-       { CRn( 9), CRm(14), Op1( 0), Op2( 2), is32, access_pmintenclr},
-
-       /* PRRR/NMRR (aka MAIR0/MAIR1): swapped by interrupt.S. */
-       { CRn(10), CRm( 2), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c10_PRRR},
-       { CRn(10), CRm( 2), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_unknown, c10_NMRR},
-
-       /* AMAIR0/AMAIR1: swapped by interrupt.S. */
-       { CRn(10), CRm( 3), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_unknown, c10_AMAIR0},
-       { CRn(10), CRm( 3), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_unknown, c10_AMAIR1},
-
-       /* ICC_SGI1R */
-       { CRm64(12), Op1( 0), is64, access_gic_sgi},
-
-       /* VBAR: swapped by interrupt.S. */
-       { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
-                       NULL, reset_val, c12_VBAR, 0x00000000 },
-
-       /* ICC_ASGI1R */
-       { CRm64(12), Op1( 1), is64, access_gic_sgi},
-       /* ICC_SGI0R */
-       { CRm64(12), Op1( 2), is64, access_gic_sgi},
-       /* ICC_SRE */
-       { CRn(12), CRm(12), Op1( 0), Op2(5), is32, access_gic_sre },
-
-       /* CONTEXTIDR/TPIDRURW/TPIDRURO/TPIDRPRW: swapped by interrupt.S. */
-       { CRn(13), CRm( 0), Op1( 0), Op2( 1), is32,
-                       access_vm_reg, reset_val, c13_CID, 0x00000000 },
-       { CRn(13), CRm( 0), Op1( 0), Op2( 2), is32,
-                       NULL, reset_unknown, c13_TID_URW },
-       { CRn(13), CRm( 0), Op1( 0), Op2( 3), is32,
-                       NULL, reset_unknown, c13_TID_URO },
-       { CRn(13), CRm( 0), Op1( 0), Op2( 4), is32,
-                       NULL, reset_unknown, c13_TID_PRIV },
-
-       /* CNTP */
-       { CRm64(14), Op1( 2), is64, access_cntp_cval},
-
-       /* CNTKCTL: swapped by interrupt.S. */
-       { CRn(14), CRm( 1), Op1( 0), Op2( 0), is32,
-                       NULL, reset_val, c14_CNTKCTL, 0x00000000 },
-
-       /* CNTP */
-       { CRn(14), CRm( 2), Op1( 0), Op2( 0), is32, access_cntp_tval },
-       { CRn(14), CRm( 2), Op1( 0), Op2( 1), is32, access_cntp_ctl },
-
-       /* The Configuration Base Address Register. */
-       { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
-};
-
-static int check_reg_table(const struct coproc_reg *table, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 1; i < n; i++) {
-               if (cmp_reg(&table[i-1], &table[i]) >= 0) {
-                       kvm_err("reg table %p out of order (%d)\n", table, i - 1);
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/* Target specific emulation tables */
-static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
-
-void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
-{
-       BUG_ON(check_reg_table(table->table, table->num));
-       target_tables[table->target] = table;
-}
-
-/* Get specific register table for this target. */
-static const struct coproc_reg *get_target_table(unsigned target, size_t *num)
-{
-       struct kvm_coproc_target_table *table;
-
-       table = target_tables[target];
-       *num = table->num;
-       return table->table;
-}
-
-#define reg_to_match_value(x)                                          \
-       ({                                                              \
-               unsigned long val;                                      \
-               val  = (x)->CRn << 11;                                  \
-               val |= (x)->CRm << 7;                                   \
-               val |= (x)->Op1 << 4;                                   \
-               val |= (x)->Op2 << 1;                                   \
-               val |= !(x)->is_64bit;                                  \
-               val;                                                    \
-        })
-
-static int match_reg(const void *key, const void *elt)
-{
-       const unsigned long pval = (unsigned long)key;
-       const struct coproc_reg *r = elt;
-
-       return pval - reg_to_match_value(r);
-}
-
-static const struct coproc_reg *find_reg(const struct coproc_params *params,
-                                        const struct coproc_reg table[],
-                                        unsigned int num)
-{
-       unsigned long pval = reg_to_match_value(params);
-
-       return bsearch((void *)pval, table, num, sizeof(table[0]), match_reg);
-}
-
-static int emulate_cp15(struct kvm_vcpu *vcpu,
-                       const struct coproc_params *params)
-{
-       size_t num;
-       const struct coproc_reg *table, *r;
-
-       trace_kvm_emulate_cp15_imp(params->Op1, params->Rt1, params->CRn,
-                                  params->CRm, params->Op2, params->is_write);
-
-       table = get_target_table(vcpu->arch.target, &num);
-
-       /* Search target-specific then generic table. */
-       r = find_reg(params, table, num);
-       if (!r)
-               r = find_reg(params, cp15_regs, ARRAY_SIZE(cp15_regs));
-
-       if (likely(r)) {
-               /* If we don't have an accessor, we should never get here! */
-               BUG_ON(!r->access);
-
-               if (likely(r->access(vcpu, params, r))) {
-                       /* Skip instruction, since it was emulated */
-                       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-               }
-       } else {
-               /* If access function fails, it should complain. */
-               kvm_err("Unsupported guest CP15 access at: %08lx [%08lx]\n",
-                       *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
-               print_cp_instr(params);
-               kvm_inject_undefined(vcpu);
-       }
-
-       return 1;
-}
-
-static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu)
-{
-       struct coproc_params params;
-
-       params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
-       params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
-       params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
-       params.is_64bit = true;
-
-       params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 16) & 0xf;
-       params.Op2 = 0;
-       params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
-       params.CRm = 0;
-
-       return params;
-}
-
-/**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       struct coproc_params params = decode_64bit_hsr(vcpu);
-
-       return emulate_cp15(vcpu, &params);
-}
-
-/**
- * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       struct coproc_params params = decode_64bit_hsr(vcpu);
-
-       /* raz_wi cp14 */
-       trap_raz_wi(vcpu, &params, NULL);
-
-       /* handled */
-       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-       return 1;
-}
-
-static void reset_coproc_regs(struct kvm_vcpu *vcpu,
-                             const struct coproc_reg *table, size_t num,
-                             unsigned long *bmap)
-{
-       unsigned long i;
-
-       for (i = 0; i < num; i++)
-               if (table[i].reset) {
-                       int reg = table[i].reg;
-
-                       table[i].reset(vcpu, &table[i]);
-                       if (reg > 0 && reg < NR_CP15_REGS) {
-                               set_bit(reg, bmap);
-                               if (table[i].is_64bit)
-                                       set_bit(reg + 1, bmap);
-                       }
-               }
-}
-
-static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
-{
-       struct coproc_params params;
-
-       params.CRm = (kvm_vcpu_get_hsr(vcpu) >> 1) & 0xf;
-       params.Rt1 = (kvm_vcpu_get_hsr(vcpu) >> 5) & 0xf;
-       params.is_write = ((kvm_vcpu_get_hsr(vcpu) & 1) == 0);
-       params.is_64bit = false;
-
-       params.CRn = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
-       params.Op1 = (kvm_vcpu_get_hsr(vcpu) >> 14) & 0x7;
-       params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
-       params.Rt2 = 0;
-
-       return params;
-}
-
-/**
- * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       struct coproc_params params = decode_32bit_hsr(vcpu);
-       return emulate_cp15(vcpu, &params);
-}
-
-/**
- * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       struct coproc_params params = decode_32bit_hsr(vcpu);
-
-       /* raz_wi cp14 */
-       trap_raz_wi(vcpu, &params, NULL);
-
-       /* handled */
-       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-       return 1;
-}
-
-/******************************************************************************
- * Userspace API
- *****************************************************************************/
-
-static bool index_to_params(u64 id, struct coproc_params *params)
-{
-       switch (id & KVM_REG_SIZE_MASK) {
-       case KVM_REG_SIZE_U32:
-               /* Any unused index bits means it's not valid. */
-               if (id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK
-                          | KVM_REG_ARM_COPROC_MASK
-                          | KVM_REG_ARM_32_CRN_MASK
-                          | KVM_REG_ARM_CRM_MASK
-                          | KVM_REG_ARM_OPC1_MASK
-                          | KVM_REG_ARM_32_OPC2_MASK))
-                       return false;
-
-               params->is_64bit = false;
-               params->CRn = ((id & KVM_REG_ARM_32_CRN_MASK)
-                              >> KVM_REG_ARM_32_CRN_SHIFT);
-               params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
-                              >> KVM_REG_ARM_CRM_SHIFT);
-               params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
-                              >> KVM_REG_ARM_OPC1_SHIFT);
-               params->Op2 = ((id & KVM_REG_ARM_32_OPC2_MASK)
-                              >> KVM_REG_ARM_32_OPC2_SHIFT);
-               return true;
-       case KVM_REG_SIZE_U64:
-               /* Any unused index bits means it's not valid. */
-               if (id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK
-                             | KVM_REG_ARM_COPROC_MASK
-                             | KVM_REG_ARM_CRM_MASK
-                             | KVM_REG_ARM_OPC1_MASK))
-                       return false;
-               params->is_64bit = true;
-               /* CRm to CRn: see cp15_to_index for details */
-               params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
-                              >> KVM_REG_ARM_CRM_SHIFT);
-               params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
-                              >> KVM_REG_ARM_OPC1_SHIFT);
-               params->Op2 = 0;
-               params->CRm = 0;
-               return true;
-       default:
-               return false;
-       }
-}
-
-/* Decode an index value, and find the cp15 coproc_reg entry. */
-static const struct coproc_reg *index_to_coproc_reg(struct kvm_vcpu *vcpu,
-                                                   u64 id)
-{
-       size_t num;
-       const struct coproc_reg *table, *r;
-       struct coproc_params params;
-
-       /* We only do cp15 for now. */
-       if ((id & KVM_REG_ARM_COPROC_MASK) >> KVM_REG_ARM_COPROC_SHIFT != 15)
-               return NULL;
-
-       if (!index_to_params(id, &params))
-               return NULL;
-
-       table = get_target_table(vcpu->arch.target, &num);
-       r = find_reg(&params, table, num);
-       if (!r)
-               r = find_reg(&params, cp15_regs, ARRAY_SIZE(cp15_regs));
-
-       /* Not saved in the cp15 array? */
-       if (r && !r->reg)
-               r = NULL;
-
-       return r;
-}
-
-/*
- * These are the invariant cp15 registers: we let the guest see the host
- * versions of these, so they're part of the guest state.
- *
- * A future CPU may provide a mechanism to present different values to
- * the guest, or a future kvm may trap them.
- */
-/* Unfortunately, there's no register-argument for mrc, so generate. */
-#define FUNCTION_FOR32(crn, crm, op1, op2, name)                       \
-       static void get_##name(struct kvm_vcpu *v,                      \
-                              const struct coproc_reg *r)              \
-       {                                                               \
-               u32 val;                                                \
-                                                                       \
-               asm volatile("mrc p15, " __stringify(op1)               \
-                            ", %0, c" __stringify(crn)                 \
-                            ", c" __stringify(crm)                     \
-                            ", " __stringify(op2) "\n" : "=r" (val));  \
-               ((struct coproc_reg *)r)->val = val;                    \
-       }
-
-FUNCTION_FOR32(0, 0, 0, 0, MIDR)
-FUNCTION_FOR32(0, 0, 0, 1, CTR)
-FUNCTION_FOR32(0, 0, 0, 2, TCMTR)
-FUNCTION_FOR32(0, 0, 0, 3, TLBTR)
-FUNCTION_FOR32(0, 0, 0, 6, REVIDR)
-FUNCTION_FOR32(0, 1, 0, 0, ID_PFR0)
-FUNCTION_FOR32(0, 1, 0, 1, ID_PFR1)
-FUNCTION_FOR32(0, 1, 0, 2, ID_DFR0)
-FUNCTION_FOR32(0, 1, 0, 3, ID_AFR0)
-FUNCTION_FOR32(0, 1, 0, 4, ID_MMFR0)
-FUNCTION_FOR32(0, 1, 0, 5, ID_MMFR1)
-FUNCTION_FOR32(0, 1, 0, 6, ID_MMFR2)
-FUNCTION_FOR32(0, 1, 0, 7, ID_MMFR3)
-FUNCTION_FOR32(0, 2, 0, 0, ID_ISAR0)
-FUNCTION_FOR32(0, 2, 0, 1, ID_ISAR1)
-FUNCTION_FOR32(0, 2, 0, 2, ID_ISAR2)
-FUNCTION_FOR32(0, 2, 0, 3, ID_ISAR3)
-FUNCTION_FOR32(0, 2, 0, 4, ID_ISAR4)
-FUNCTION_FOR32(0, 2, 0, 5, ID_ISAR5)
-FUNCTION_FOR32(0, 0, 1, 1, CLIDR)
-FUNCTION_FOR32(0, 0, 1, 7, AIDR)
-
-/* ->val is filled in by kvm_invariant_coproc_table_init() */
-static struct coproc_reg invariant_cp15[] = {
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 0), is32, NULL, get_MIDR },
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 1), is32, NULL, get_CTR },
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 2), is32, NULL, get_TCMTR },
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 3), is32, NULL, get_TLBTR },
-       { CRn( 0), CRm( 0), Op1( 0), Op2( 6), is32, NULL, get_REVIDR },
-
-       { CRn( 0), CRm( 0), Op1( 1), Op2( 1), is32, NULL, get_CLIDR },
-       { CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
-
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 0), is32, NULL, get_ID_PFR0 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 1), is32, NULL, get_ID_PFR1 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 2), is32, NULL, get_ID_DFR0 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 3), is32, NULL, get_ID_AFR0 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 4), is32, NULL, get_ID_MMFR0 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 5), is32, NULL, get_ID_MMFR1 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 6), is32, NULL, get_ID_MMFR2 },
-       { CRn( 0), CRm( 1), Op1( 0), Op2( 7), is32, NULL, get_ID_MMFR3 },
-
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 0), is32, NULL, get_ID_ISAR0 },
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 1), is32, NULL, get_ID_ISAR1 },
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 2), is32, NULL, get_ID_ISAR2 },
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 3), is32, NULL, get_ID_ISAR3 },
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 4), is32, NULL, get_ID_ISAR4 },
-       { CRn( 0), CRm( 2), Op1( 0), Op2( 5), is32, NULL, get_ID_ISAR5 },
-};
-
-/*
- * Reads a register value from a userspace address to a kernel
- * variable. Make sure that register size matches sizeof(*__val).
- */
-static int reg_from_user(void *val, const void __user *uaddr, u64 id)
-{
-       if (copy_from_user(val, uaddr, KVM_REG_SIZE(id)) != 0)
-               return -EFAULT;
-       return 0;
-}
-
-/*
- * Writes a register value to a userspace address from a kernel variable.
- * Make sure that register size matches sizeof(*__val).
- */
-static int reg_to_user(void __user *uaddr, const void *val, u64 id)
-{
-       if (copy_to_user(uaddr, val, KVM_REG_SIZE(id)) != 0)
-               return -EFAULT;
-       return 0;
-}
-
-static int get_invariant_cp15(u64 id, void __user *uaddr)
-{
-       struct coproc_params params;
-       const struct coproc_reg *r;
-       int ret;
-
-       if (!index_to_params(id, &params))
-               return -ENOENT;
-
-       r = find_reg(&params, invariant_cp15, ARRAY_SIZE(invariant_cp15));
-       if (!r)
-               return -ENOENT;
-
-       ret = -ENOENT;
-       if (KVM_REG_SIZE(id) == 4) {
-               u32 val = r->val;
-
-               ret = reg_to_user(uaddr, &val, id);
-       } else if (KVM_REG_SIZE(id) == 8) {
-               ret = reg_to_user(uaddr, &r->val, id);
-       }
-       return ret;
-}
-
-static int set_invariant_cp15(u64 id, void __user *uaddr)
-{
-       struct coproc_params params;
-       const struct coproc_reg *r;
-       int err;
-       u64 val;
-
-       if (!index_to_params(id, &params))
-               return -ENOENT;
-       r = find_reg(&params, invariant_cp15, ARRAY_SIZE(invariant_cp15));
-       if (!r)
-               return -ENOENT;
-
-       err = -ENOENT;
-       if (KVM_REG_SIZE(id) == 4) {
-               u32 val32;
-
-               err = reg_from_user(&val32, uaddr, id);
-               if (!err)
-                       val = val32;
-       } else if (KVM_REG_SIZE(id) == 8) {
-               err = reg_from_user(&val, uaddr, id);
-       }
-       if (err)
-               return err;
-
-       /* This is what we mean by invariant: you can't change it. */
-       if (r->val != val)
-               return -EINVAL;
-
-       return 0;
-}
-
-static bool is_valid_cache(u32 val)
-{
-       u32 level, ctype;
-
-       if (val >= CSSELR_MAX)
-               return false;
-
-       /* Bottom bit is Instruction or Data bit.  Next 3 bits are level. */
-        level = (val >> 1);
-        ctype = (cache_levels >> (level * 3)) & 7;
-
-       switch (ctype) {
-       case 0: /* No cache */
-               return false;
-       case 1: /* Instruction cache only */
-               return (val & 1);
-       case 2: /* Data cache only */
-       case 4: /* Unified cache */
-               return !(val & 1);
-       case 3: /* Separate instruction and data caches */
-               return true;
-       default: /* Reserved: we can't know instruction or data. */
-               return false;
-       }
-}
-
-/* Which cache CCSIDR represents depends on CSSELR value. */
-static u32 get_ccsidr(u32 csselr)
-{
-       u32 ccsidr;
-
-       /* Make sure noone else changes CSSELR during this! */
-       local_irq_disable();
-       /* Put value into CSSELR */
-       asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
-       isb();
-       /* Read result out of CCSIDR */
-       asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
-       local_irq_enable();
-
-       return ccsidr;
-}
-
-static int demux_c15_get(u64 id, void __user *uaddr)
-{
-       u32 val;
-       u32 __user *uval = uaddr;
-
-       /* Fail if we have unknown bits set. */
-       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
-                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
-               return -ENOENT;
-
-       switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
-       case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-               if (KVM_REG_SIZE(id) != 4)
-                       return -ENOENT;
-               val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-                       >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-               if (!is_valid_cache(val))
-                       return -ENOENT;
-
-               return put_user(get_ccsidr(val), uval);
-       default:
-               return -ENOENT;
-       }
-}
-
-static int demux_c15_set(u64 id, void __user *uaddr)
-{
-       u32 val, newval;
-       u32 __user *uval = uaddr;
-
-       /* Fail if we have unknown bits set. */
-       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
-                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
-               return -ENOENT;
-
-       switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
-       case KVM_REG_ARM_DEMUX_ID_CCSIDR:
-               if (KVM_REG_SIZE(id) != 4)
-                       return -ENOENT;
-               val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
-                       >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
-               if (!is_valid_cache(val))
-                       return -ENOENT;
-
-               if (get_user(newval, uval))
-                       return -EFAULT;
-
-               /* This is also invariant: you can't change it. */
-               if (newval != get_ccsidr(val))
-                       return -EINVAL;
-               return 0;
-       default:
-               return -ENOENT;
-       }
-}
-
-#ifdef CONFIG_VFPv3
-static const int vfp_sysregs[] = { KVM_REG_ARM_VFP_FPEXC,
-                                  KVM_REG_ARM_VFP_FPSCR,
-                                  KVM_REG_ARM_VFP_FPINST,
-                                  KVM_REG_ARM_VFP_FPINST2,
-                                  KVM_REG_ARM_VFP_MVFR0,
-                                  KVM_REG_ARM_VFP_MVFR1,
-                                  KVM_REG_ARM_VFP_FPSID };
-
-static unsigned int num_fp_regs(void)
-{
-       if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK) >> MVFR0_A_SIMD_BIT) == 2)
-               return 32;
-       else
-               return 16;
-}
-
-static unsigned int num_vfp_regs(void)
-{
-       /* Normal FP regs + control regs. */
-       return num_fp_regs() + ARRAY_SIZE(vfp_sysregs);
-}
-
-static int copy_vfp_regids(u64 __user *uindices)
-{
-       unsigned int i;
-       const u64 u32reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP;
-       const u64 u64reg = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
-
-       for (i = 0; i < num_fp_regs(); i++) {
-               if (put_user((u64reg | KVM_REG_ARM_VFP_BASE_REG) + i,
-                            uindices))
-                       return -EFAULT;
-               uindices++;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(vfp_sysregs); i++) {
-               if (put_user(u32reg | vfp_sysregs[i], uindices))
-                       return -EFAULT;
-               uindices++;
-       }
-
-       return num_vfp_regs();
-}
-
-static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
-{
-       u32 vfpid = (id & KVM_REG_ARM_VFP_MASK);
-       u32 val;
-
-       /* Fail if we have unknown bits set. */
-       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
-                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
-               return -ENOENT;
-
-       if (vfpid < num_fp_regs()) {
-               if (KVM_REG_SIZE(id) != 8)
-                       return -ENOENT;
-               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpregs[vfpid],
-                                  id);
-       }
-
-       /* FP control registers are all 32 bit. */
-       if (KVM_REG_SIZE(id) != 4)
-               return -ENOENT;
-
-       switch (vfpid) {
-       case KVM_REG_ARM_VFP_FPEXC:
-               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpexc, id);
-       case KVM_REG_ARM_VFP_FPSCR:
-               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpscr, id);
-       case KVM_REG_ARM_VFP_FPINST:
-               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpinst, id);
-       case KVM_REG_ARM_VFP_FPINST2:
-               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpinst2, id);
-       case KVM_REG_ARM_VFP_MVFR0:
-               val = fmrx(MVFR0);
-               return reg_to_user(uaddr, &val, id);
-       case KVM_REG_ARM_VFP_MVFR1:
-               val = fmrx(MVFR1);
-               return reg_to_user(uaddr, &val, id);
-       case KVM_REG_ARM_VFP_FPSID:
-               val = fmrx(FPSID);
-               return reg_to_user(uaddr, &val, id);
-       default:
-               return -ENOENT;
-       }
-}
-
-static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
-{
-       u32 vfpid = (id & KVM_REG_ARM_VFP_MASK);
-       u32 val;
-
-       /* Fail if we have unknown bits set. */
-       if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
-                  | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
-               return -ENOENT;
-
-       if (vfpid < num_fp_regs()) {
-               if (KVM_REG_SIZE(id) != 8)
-                       return -ENOENT;
-               return reg_from_user(&vcpu->arch.ctxt.vfp.fpregs[vfpid],
-                                    uaddr, id);
-       }
-
-       /* FP control registers are all 32 bit. */
-       if (KVM_REG_SIZE(id) != 4)
-               return -ENOENT;
-
-       switch (vfpid) {
-       case KVM_REG_ARM_VFP_FPEXC:
-               return reg_from_user(&vcpu->arch.ctxt.vfp.fpexc, uaddr, id);
-       case KVM_REG_ARM_VFP_FPSCR:
-               return reg_from_user(&vcpu->arch.ctxt.vfp.fpscr, uaddr, id);
-       case KVM_REG_ARM_VFP_FPINST:
-               return reg_from_user(&vcpu->arch.ctxt.vfp.fpinst, uaddr, id);
-       case KVM_REG_ARM_VFP_FPINST2:
-               return reg_from_user(&vcpu->arch.ctxt.vfp.fpinst2, uaddr, id);
-       /* These are invariant. */
-       case KVM_REG_ARM_VFP_MVFR0:
-               if (reg_from_user(&val, uaddr, id))
-                       return -EFAULT;
-               if (val != fmrx(MVFR0))
-                       return -EINVAL;
-               return 0;
-       case KVM_REG_ARM_VFP_MVFR1:
-               if (reg_from_user(&val, uaddr, id))
-                       return -EFAULT;
-               if (val != fmrx(MVFR1))
-                       return -EINVAL;
-               return 0;
-       case KVM_REG_ARM_VFP_FPSID:
-               if (reg_from_user(&val, uaddr, id))
-                       return -EFAULT;
-               if (val != fmrx(FPSID))
-                       return -EINVAL;
-               return 0;
-       default:
-               return -ENOENT;
-       }
-}
-#else /* !CONFIG_VFPv3 */
-static unsigned int num_vfp_regs(void)
-{
-       return 0;
-}
-
-static int copy_vfp_regids(u64 __user *uindices)
-{
-       return 0;
-}
-
-static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
-{
-       return -ENOENT;
-}
-
-static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
-{
-       return -ENOENT;
-}
-#endif /* !CONFIG_VFPv3 */
-
-int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       const struct coproc_reg *r;
-       void __user *uaddr = (void __user *)(long)reg->addr;
-       int ret;
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
-               return demux_c15_get(reg->id, uaddr);
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_VFP)
-               return vfp_get_reg(vcpu, reg->id, uaddr);
-
-       r = index_to_coproc_reg(vcpu, reg->id);
-       if (!r)
-               return get_invariant_cp15(reg->id, uaddr);
-
-       ret = -ENOENT;
-       if (KVM_REG_SIZE(reg->id) == 8) {
-               u64 val;
-
-               val = vcpu_cp15_reg64_get(vcpu, r);
-               ret = reg_to_user(uaddr, &val, reg->id);
-       } else if (KVM_REG_SIZE(reg->id) == 4) {
-               ret = reg_to_user(uaddr, &vcpu_cp15(vcpu, r->reg), reg->id);
-       }
-
-       return ret;
-}
-
-int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       const struct coproc_reg *r;
-       void __user *uaddr = (void __user *)(long)reg->addr;
-       int ret;
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
-               return demux_c15_set(reg->id, uaddr);
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_VFP)
-               return vfp_set_reg(vcpu, reg->id, uaddr);
-
-       r = index_to_coproc_reg(vcpu, reg->id);
-       if (!r)
-               return set_invariant_cp15(reg->id, uaddr);
-
-       ret = -ENOENT;
-       if (KVM_REG_SIZE(reg->id) == 8) {
-               u64 val;
-
-               ret = reg_from_user(&val, uaddr, reg->id);
-               if (!ret)
-                       vcpu_cp15_reg64_set(vcpu, r, val);
-       } else if (KVM_REG_SIZE(reg->id) == 4) {
-               ret = reg_from_user(&vcpu_cp15(vcpu, r->reg), uaddr, reg->id);
-       }
-
-       return ret;
-}
-
-static unsigned int num_demux_regs(void)
-{
-       unsigned int i, count = 0;
-
-       for (i = 0; i < CSSELR_MAX; i++)
-               if (is_valid_cache(i))
-                       count++;
-
-       return count;
-}
-
-static int write_demux_regids(u64 __user *uindices)
-{
-       u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
-       unsigned int i;
-
-       val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
-       for (i = 0; i < CSSELR_MAX; i++) {
-               if (!is_valid_cache(i))
-                       continue;
-               if (put_user(val | i, uindices))
-                       return -EFAULT;
-               uindices++;
-       }
-       return 0;
-}
-
-static u64 cp15_to_index(const struct coproc_reg *reg)
-{
-       u64 val = KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT);
-       if (reg->is_64bit) {
-               val |= KVM_REG_SIZE_U64;
-               val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               /*
-                * CRn always denotes the primary coproc. reg. nr. for the
-                * in-kernel representation, but the user space API uses the
-                * CRm for the encoding, because it is modelled after the
-                * MRRC/MCRR instructions: see the ARM ARM rev. c page
-                * B3-1445
-                */
-               val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
-       } else {
-               val |= KVM_REG_SIZE_U32;
-               val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
-               val |= (reg->Op2 << KVM_REG_ARM_32_OPC2_SHIFT);
-               val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
-               val |= (reg->CRn << KVM_REG_ARM_32_CRN_SHIFT);
-       }
-       return val;
-}
-
-static bool copy_reg_to_user(const struct coproc_reg *reg, u64 __user **uind)
-{
-       if (!*uind)
-               return true;
-
-       if (put_user(cp15_to_index(reg), *uind))
-               return false;
-
-       (*uind)++;
-       return true;
-}
-
-/* Assumed ordered tables, see kvm_coproc_table_init. */
-static int walk_cp15(struct kvm_vcpu *vcpu, u64 __user *uind)
-{
-       const struct coproc_reg *i1, *i2, *end1, *end2;
-       unsigned int total = 0;
-       size_t num;
-
-       /* We check for duplicates here, to allow arch-specific overrides. */
-       i1 = get_target_table(vcpu->arch.target, &num);
-       end1 = i1 + num;
-       i2 = cp15_regs;
-       end2 = cp15_regs + ARRAY_SIZE(cp15_regs);
-
-       BUG_ON(i1 == end1 || i2 == end2);
-
-       /* Walk carefully, as both tables may refer to the same register. */
-       while (i1 || i2) {
-               int cmp = cmp_reg(i1, i2);
-               /* target-specific overrides generic entry. */
-               if (cmp <= 0) {
-                       /* Ignore registers we trap but don't save. */
-                       if (i1->reg) {
-                               if (!copy_reg_to_user(i1, &uind))
-                                       return -EFAULT;
-                               total++;
-                       }
-               } else {
-                       /* Ignore registers we trap but don't save. */
-                       if (i2->reg) {
-                               if (!copy_reg_to_user(i2, &uind))
-                                       return -EFAULT;
-                               total++;
-                       }
-               }
-
-               if (cmp <= 0 && ++i1 == end1)
-                       i1 = NULL;
-               if (cmp >= 0 && ++i2 == end2)
-                       i2 = NULL;
-       }
-       return total;
-}
-
-unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu)
-{
-       return ARRAY_SIZE(invariant_cp15)
-               + num_demux_regs()
-               + num_vfp_regs()
-               + walk_cp15(vcpu, (u64 __user *)NULL);
-}
-
-int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
-{
-       unsigned int i;
-       int err;
-
-       /* Then give them all the invariant registers' indices. */
-       for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++) {
-               if (put_user(cp15_to_index(&invariant_cp15[i]), uindices))
-                       return -EFAULT;
-               uindices++;
-       }
-
-       err = walk_cp15(vcpu, uindices);
-       if (err < 0)
-               return err;
-       uindices += err;
-
-       err = copy_vfp_regids(uindices);
-       if (err < 0)
-               return err;
-       uindices += err;
-
-       return write_demux_regids(uindices);
-}
-
-void kvm_coproc_table_init(void)
-{
-       unsigned int i;
-
-       /* Make sure tables are unique and in order. */
-       BUG_ON(check_reg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
-       BUG_ON(check_reg_table(invariant_cp15, ARRAY_SIZE(invariant_cp15)));
-
-       /* We abuse the reset function to overwrite the table itself. */
-       for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++)
-               invariant_cp15[i].reset(NULL, &invariant_cp15[i]);
-
-       /*
-        * CLIDR format is awkward, so clean it up.  See ARM B4.1.20:
-        *
-        *   If software reads the Cache Type fields from Ctype1
-        *   upwards, once it has seen a value of 0b000, no caches
-        *   exist at further-out levels of the hierarchy. So, for
-        *   example, if Ctype3 is the first Cache Type field with a
-        *   value of 0b000, the values of Ctype4 to Ctype7 must be
-        *   ignored.
-        */
-       asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r" (cache_levels));
-       for (i = 0; i < 7; i++)
-               if (((cache_levels >> (i*3)) & 7) == 0)
-                       break;
-       /* Clear all higher bits. */
-       cache_levels &= (1 << (i*3))-1;
-}
-
-/**
- * kvm_reset_coprocs - sets cp15 registers to reset value
- * @vcpu: The VCPU pointer
- *
- * This function finds the right table above and sets the registers on the
- * virtual CPU struct to their architecturally defined reset values.
- */
-void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
-{
-       size_t num;
-       const struct coproc_reg *table;
-       DECLARE_BITMAP(bmap, NR_CP15_REGS) = { 0, };
-
-       /* Generic chip reset first (so target could override). */
-       reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs), bmap);
-
-       table = get_target_table(vcpu->arch.target, &num);
-       reset_coproc_regs(vcpu, table, num, bmap);
-
-       for (num = 1; num < NR_CP15_REGS; num++)
-               WARN(!test_bit(num, bmap),
-                    "Didn't reset vcpu_cp15(vcpu, %zi)", num);
-}
diff --git a/arch/arm/kvm/coproc.h b/arch/arm/kvm/coproc.h
deleted file mode 100644 (file)
index 637065b..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Authors: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#ifndef __ARM_KVM_COPROC_LOCAL_H__
-#define __ARM_KVM_COPROC_LOCAL_H__
-
-struct coproc_params {
-       unsigned long CRn;
-       unsigned long CRm;
-       unsigned long Op1;
-       unsigned long Op2;
-       unsigned long Rt1;
-       unsigned long Rt2;
-       bool is_64bit;
-       bool is_write;
-};
-
-struct coproc_reg {
-       /* MRC/MCR/MRRC/MCRR instruction which accesses it. */
-       unsigned long CRn;
-       unsigned long CRm;
-       unsigned long Op1;
-       unsigned long Op2;
-
-       bool is_64bit;
-
-       /* Trapped access from guest, if non-NULL. */
-       bool (*access)(struct kvm_vcpu *,
-                      const struct coproc_params *,
-                      const struct coproc_reg *);
-
-       /* Initialization for vcpu. */
-       void (*reset)(struct kvm_vcpu *, const struct coproc_reg *);
-
-       /* Index into vcpu_cp15(vcpu, ...), or 0 if we don't need to save it. */
-       unsigned long reg;
-
-       /* Value (usually reset value) */
-       u64 val;
-};
-
-static inline void print_cp_instr(const struct coproc_params *p)
-{
-       /* Look, we even formatted it for you to paste into the table! */
-       if (p->is_64bit) {
-               kvm_pr_unimpl(" { CRm64(%2lu), Op1(%2lu), is64, func_%s },\n",
-                             p->CRn, p->Op1, p->is_write ? "write" : "read");
-       } else {
-               kvm_pr_unimpl(" { CRn(%2lu), CRm(%2lu), Op1(%2lu), Op2(%2lu), is32,"
-                             " func_%s },\n",
-                             p->CRn, p->CRm, p->Op1, p->Op2,
-                             p->is_write ? "write" : "read");
-       }
-}
-
-static inline bool ignore_write(struct kvm_vcpu *vcpu,
-                               const struct coproc_params *p)
-{
-       return true;
-}
-
-static inline bool read_zero(struct kvm_vcpu *vcpu,
-                            const struct coproc_params *p)
-{
-       *vcpu_reg(vcpu, p->Rt1) = 0;
-       return true;
-}
-
-/* Reset functions */
-static inline void reset_unknown(struct kvm_vcpu *vcpu,
-                                const struct coproc_reg *r)
-{
-       BUG_ON(!r->reg);
-       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
-       vcpu_cp15(vcpu, r->reg) = 0xdecafbad;
-}
-
-static inline void reset_val(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
-{
-       BUG_ON(!r->reg);
-       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
-       vcpu_cp15(vcpu, r->reg) = r->val;
-}
-
-static inline void reset_unknown64(struct kvm_vcpu *vcpu,
-                                  const struct coproc_reg *r)
-{
-       BUG_ON(!r->reg);
-       BUG_ON(r->reg + 1 >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
-
-       vcpu_cp15(vcpu, r->reg) = 0xdecafbad;
-       vcpu_cp15(vcpu, r->reg+1) = 0xd0c0ffee;
-}
-
-static inline int cmp_reg(const struct coproc_reg *i1,
-                         const struct coproc_reg *i2)
-{
-       BUG_ON(i1 == i2);
-       if (!i1)
-               return 1;
-       else if (!i2)
-               return -1;
-       if (i1->CRn != i2->CRn)
-               return i1->CRn - i2->CRn;
-       if (i1->CRm != i2->CRm)
-               return i1->CRm - i2->CRm;
-       if (i1->Op1 != i2->Op1)
-               return i1->Op1 - i2->Op1;
-       if (i1->Op2 != i2->Op2)
-               return i1->Op2 - i2->Op2;
-       return i2->is_64bit - i1->is_64bit;
-}
-
-
-#define CRn(_x)                .CRn = _x
-#define CRm(_x)        .CRm = _x
-#define CRm64(_x)       .CRn = _x, .CRm = 0
-#define Op1(_x)        .Op1 = _x
-#define Op2(_x)        .Op2 = _x
-#define is64           .is_64bit = true
-#define is32           .is_64bit = false
-
-bool access_vm_reg(struct kvm_vcpu *vcpu,
-                  const struct coproc_params *p,
-                  const struct coproc_reg *r);
-
-#endif /* __ARM_KVM_COPROC_LOCAL_H__ */
diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c
deleted file mode 100644 (file)
index 36bf154..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Authors: Rusty Russell <rusty@rustcorp.au>
- *          Christoffer Dall <c.dall@virtualopensystems.com>
- */
-#include <linux/kvm_host.h>
-#include <asm/kvm_coproc.h>
-#include <asm/kvm_emulate.h>
-#include <linux/init.h>
-
-#include "coproc.h"
-
-/*
- * A15-specific CP15 registers.
- * CRn denotes the primary register number, but is copied to the CRm in the
- * user space API for 64-bit register access in line with the terminology used
- * in the ARM ARM.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
- *            registers preceding 32-bit ones.
- */
-static const struct coproc_reg a15_regs[] = {
-       /* SCTLR: swapped by interrupt.S. */
-       { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_val, c1_SCTLR, 0x00C50078 },
-};
-
-static struct kvm_coproc_target_table a15_target_table = {
-       .target = KVM_ARM_TARGET_CORTEX_A15,
-       .table = a15_regs,
-       .num = ARRAY_SIZE(a15_regs),
-};
-
-static int __init coproc_a15_init(void)
-{
-       kvm_register_target_coproc_table(&a15_target_table);
-       return 0;
-}
-late_initcall(coproc_a15_init);
diff --git a/arch/arm/kvm/coproc_a7.c b/arch/arm/kvm/coproc_a7.c
deleted file mode 100644 (file)
index 40f643e..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Copyright (C) 2013 - ARM Ltd
- *
- * Authors: Rusty Russell <rusty@rustcorp.au>
- *          Christoffer Dall <c.dall@virtualopensystems.com>
- *          Jonathan Austin <jonathan.austin@arm.com>
- */
-#include <linux/kvm_host.h>
-#include <asm/kvm_coproc.h>
-#include <asm/kvm_emulate.h>
-#include <linux/init.h>
-
-#include "coproc.h"
-
-/*
- * Cortex-A7 specific CP15 registers.
- * CRn denotes the primary register number, but is copied to the CRm in the
- * user space API for 64-bit register access in line with the terminology used
- * in the ARM ARM.
- * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
- *            registers preceding 32-bit ones.
- */
-static const struct coproc_reg a7_regs[] = {
-       /* SCTLR: swapped by interrupt.S. */
-       { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32,
-                       access_vm_reg, reset_val, c1_SCTLR, 0x00C50878 },
-};
-
-static struct kvm_coproc_target_table a7_target_table = {
-       .target = KVM_ARM_TARGET_CORTEX_A7,
-       .table = a7_regs,
-       .num = ARRAY_SIZE(a7_regs),
-};
-
-static int __init coproc_a7_init(void)
-{
-       kvm_register_target_coproc_table(&a7_target_table);
-       return 0;
-}
-late_initcall(coproc_a7_init);
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
deleted file mode 100644 (file)
index 29bb852..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/mm.h>
-#include <linux/kvm_host.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_emulate.h>
-#include <asm/opcodes.h>
-#include <trace/events/kvm.h>
-
-#include "trace.h"
-
-#define VCPU_NR_MODES          6
-#define VCPU_REG_OFFSET_USR    0
-#define VCPU_REG_OFFSET_FIQ    1
-#define VCPU_REG_OFFSET_IRQ    2
-#define VCPU_REG_OFFSET_SVC    3
-#define VCPU_REG_OFFSET_ABT    4
-#define VCPU_REG_OFFSET_UND    5
-#define REG_OFFSET(_reg) \
-       (offsetof(struct kvm_regs, _reg) / sizeof(u32))
-
-#define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num])
-
-static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {
-       /* USR/SYS Registers */
-       [VCPU_REG_OFFSET_USR] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
-               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
-               USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
-       },
-
-       /* FIQ Registers */
-       [VCPU_REG_OFFSET_FIQ] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7),
-               REG_OFFSET(fiq_regs[0]), /* r8 */
-               REG_OFFSET(fiq_regs[1]), /* r9 */
-               REG_OFFSET(fiq_regs[2]), /* r10 */
-               REG_OFFSET(fiq_regs[3]), /* r11 */
-               REG_OFFSET(fiq_regs[4]), /* r12 */
-               REG_OFFSET(fiq_regs[5]), /* r13 */
-               REG_OFFSET(fiq_regs[6]), /* r14 */
-       },
-
-       /* IRQ Registers */
-       [VCPU_REG_OFFSET_IRQ] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
-               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
-               USR_REG_OFFSET(12),
-               REG_OFFSET(irq_regs[0]), /* r13 */
-               REG_OFFSET(irq_regs[1]), /* r14 */
-       },
-
-       /* SVC Registers */
-       [VCPU_REG_OFFSET_SVC] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
-               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
-               USR_REG_OFFSET(12),
-               REG_OFFSET(svc_regs[0]), /* r13 */
-               REG_OFFSET(svc_regs[1]), /* r14 */
-       },
-
-       /* ABT Registers */
-       [VCPU_REG_OFFSET_ABT] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
-               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
-               USR_REG_OFFSET(12),
-               REG_OFFSET(abt_regs[0]), /* r13 */
-               REG_OFFSET(abt_regs[1]), /* r14 */
-       },
-
-       /* UND Registers */
-       [VCPU_REG_OFFSET_UND] = {
-               USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
-               USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
-               USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
-               USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
-               USR_REG_OFFSET(12),
-               REG_OFFSET(und_regs[0]), /* r13 */
-               REG_OFFSET(und_regs[1]), /* r14 */
-       },
-};
-
-/*
- * Return a pointer to the register number valid in the current mode of
- * the virtual CPU.
- */
-unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
-{
-       unsigned long *reg_array = (unsigned long *)&vcpu->arch.ctxt.gp_regs;
-       unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
-
-       switch (mode) {
-       case USR_MODE...SVC_MODE:
-               mode &= ~MODE32_BIT; /* 0 ... 3 */
-               break;
-
-       case ABT_MODE:
-               mode = VCPU_REG_OFFSET_ABT;
-               break;
-
-       case UND_MODE:
-               mode = VCPU_REG_OFFSET_UND;
-               break;
-
-       case SYSTEM_MODE:
-               mode = VCPU_REG_OFFSET_USR;
-               break;
-
-       default:
-               BUG();
-       }
-
-       return reg_array + vcpu_reg_offsets[mode][reg_num];
-}
-
-/*
- * Return the SPSR for the current mode of the virtual CPU.
- */
-unsigned long *__vcpu_spsr(struct kvm_vcpu *vcpu)
-{
-       unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
-       switch (mode) {
-       case SVC_MODE:
-               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_SVC_spsr;
-       case ABT_MODE:
-               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_ABT_spsr;
-       case UND_MODE:
-               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_UND_spsr;
-       case IRQ_MODE:
-               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_IRQ_spsr;
-       case FIQ_MODE:
-               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_FIQ_spsr;
-       default:
-               BUG();
-       }
-}
-
-/******************************************************************************
- * Inject exceptions into the guest
- */
-
-/**
- * kvm_inject_vabt - inject an async abort / SError into the guest
- * @vcpu: The VCPU to receive the exception
- *
- * It is assumed that this code is called from the VCPU thread and that the
- * VCPU therefore is not currently executing guest code.
- */
-void kvm_inject_vabt(struct kvm_vcpu *vcpu)
-{
-       *vcpu_hcr(vcpu) |= HCR_VA;
-}
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
deleted file mode 100644 (file)
index 9f7ae0d..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/kvm_host.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <kvm/arm_psci.h>
-#include <asm/cputype.h>
-#include <linux/uaccess.h>
-#include <asm/kvm.h>
-#include <asm/kvm_emulate.h>
-#include <asm/kvm_coproc.h>
-
-#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM }
-#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU }
-
-struct kvm_stats_debugfs_item debugfs_entries[] = {
-       VCPU_STAT(halt_successful_poll),
-       VCPU_STAT(halt_attempted_poll),
-       VCPU_STAT(halt_poll_invalid),
-       VCPU_STAT(halt_wakeup),
-       VCPU_STAT(hvc_exit_stat),
-       VCPU_STAT(wfe_exit_stat),
-       VCPU_STAT(wfi_exit_stat),
-       VCPU_STAT(mmio_exit_user),
-       VCPU_STAT(mmio_exit_kernel),
-       VCPU_STAT(exits),
-       { NULL }
-};
-
-static u64 core_reg_offset_from_id(u64 id)
-{
-       return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
-}
-
-static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       u32 __user *uaddr = (u32 __user *)(long)reg->addr;
-       struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs;
-       u64 off;
-
-       if (KVM_REG_SIZE(reg->id) != 4)
-               return -ENOENT;
-
-       /* Our ID is an index into the kvm_regs struct. */
-       off = core_reg_offset_from_id(reg->id);
-       if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
-               return -ENOENT;
-
-       return put_user(((u32 *)regs)[off], uaddr);
-}
-
-static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       u32 __user *uaddr = (u32 __user *)(long)reg->addr;
-       struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs;
-       u64 off, val;
-
-       if (KVM_REG_SIZE(reg->id) != 4)
-               return -ENOENT;
-
-       /* Our ID is an index into the kvm_regs struct. */
-       off = core_reg_offset_from_id(reg->id);
-       if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
-               return -ENOENT;
-
-       if (get_user(val, uaddr) != 0)
-               return -EFAULT;
-
-       if (off == KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr)) {
-               unsigned long mode = val & MODE_MASK;
-               switch (mode) {
-               case USR_MODE:
-               case FIQ_MODE:
-               case IRQ_MODE:
-               case SVC_MODE:
-               case ABT_MODE:
-               case UND_MODE:
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       ((u32 *)regs)[off] = val;
-       return 0;
-}
-
-int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-       return -EINVAL;
-}
-
-int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
-{
-       return -EINVAL;
-}
-
-#define NUM_TIMER_REGS 3
-
-static bool is_timer_reg(u64 index)
-{
-       switch (index) {
-       case KVM_REG_ARM_TIMER_CTL:
-       case KVM_REG_ARM_TIMER_CNT:
-       case KVM_REG_ARM_TIMER_CVAL:
-               return true;
-       }
-       return false;
-}
-
-static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
-{
-       if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
-               return -EFAULT;
-       uindices++;
-       if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
-               return -EFAULT;
-       uindices++;
-       if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       void __user *uaddr = (void __user *)(long)reg->addr;
-       u64 val;
-       int ret;
-
-       ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id));
-       if (ret != 0)
-               return -EFAULT;
-
-       return kvm_arm_timer_set_reg(vcpu, reg->id, val);
-}
-
-static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       void __user *uaddr = (void __user *)(long)reg->addr;
-       u64 val;
-
-       val = kvm_arm_timer_get_reg(vcpu, reg->id);
-       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
-}
-
-static unsigned long num_core_regs(void)
-{
-       return sizeof(struct kvm_regs) / sizeof(u32);
-}
-
-/**
- * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
- *
- * This is for all registers.
- */
-unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
-{
-       return num_core_regs() + kvm_arm_num_coproc_regs(vcpu)
-               + kvm_arm_get_fw_num_regs(vcpu)
-               + NUM_TIMER_REGS;
-}
-
-/**
- * kvm_arm_copy_reg_indices - get indices of all registers.
- *
- * We do core registers right here, then we append coproc regs.
- */
-int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
-{
-       unsigned int i;
-       const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE;
-       int ret;
-
-       for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) {
-               if (put_user(core_reg | i, uindices))
-                       return -EFAULT;
-               uindices++;
-       }
-
-       ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
-       if (ret)
-               return ret;
-       uindices += kvm_arm_get_fw_num_regs(vcpu);
-
-       ret = copy_timer_indices(vcpu, uindices);
-       if (ret)
-               return ret;
-       uindices += NUM_TIMER_REGS;
-
-       return kvm_arm_copy_coproc_indices(vcpu, uindices);
-}
-
-int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       /* We currently use nothing arch-specific in upper 32 bits */
-       if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
-               return -EINVAL;
-
-       /* Register group 16 means we want a core register. */
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-               return get_core_reg(vcpu, reg);
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-               return kvm_arm_get_fw_reg(vcpu, reg);
-
-       if (is_timer_reg(reg->id))
-               return get_timer_reg(vcpu, reg);
-
-       return kvm_arm_coproc_get_reg(vcpu, reg);
-}
-
-int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
-{
-       /* We currently use nothing arch-specific in upper 32 bits */
-       if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
-               return -EINVAL;
-
-       /* Register group 16 means we set a core register. */
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-               return set_core_reg(vcpu, reg);
-
-       if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-               return kvm_arm_set_fw_reg(vcpu, reg);
-
-       if (is_timer_reg(reg->id))
-               return set_timer_reg(vcpu, reg);
-
-       return kvm_arm_coproc_set_reg(vcpu, reg);
-}
-
-int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
-                                 struct kvm_sregs *sregs)
-{
-       return -EINVAL;
-}
-
-int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
-                                 struct kvm_sregs *sregs)
-{
-       return -EINVAL;
-}
-
-
-int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
-                             struct kvm_vcpu_events *events)
-{
-       events->exception.serror_pending = !!(*vcpu_hcr(vcpu) & HCR_VA);
-
-       /*
-        * We never return a pending ext_dabt here because we deliver it to
-        * the virtual CPU directly when setting the event and it's no longer
-        * 'pending' at this point.
-        */
-
-       return 0;
-}
-
-int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
-                             struct kvm_vcpu_events *events)
-{
-       bool serror_pending = events->exception.serror_pending;
-       bool has_esr = events->exception.serror_has_esr;
-       bool ext_dabt_pending = events->exception.ext_dabt_pending;
-
-       if (serror_pending && has_esr)
-               return -EINVAL;
-       else if (serror_pending)
-               kvm_inject_vabt(vcpu);
-
-       if (ext_dabt_pending)
-               kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
-
-       return 0;
-}
-
-int __attribute_const__ kvm_target_cpu(void)
-{
-       switch (read_cpuid_part()) {
-       case ARM_CPU_PART_CORTEX_A7:
-               return KVM_ARM_TARGET_CORTEX_A7;
-       case ARM_CPU_PART_CORTEX_A15:
-               return KVM_ARM_TARGET_CORTEX_A15;
-       default:
-               return -EINVAL;
-       }
-}
-
-int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init)
-{
-       int target = kvm_target_cpu();
-
-       if (target < 0)
-               return -ENODEV;
-
-       memset(init, 0, sizeof(*init));
-
-       /*
-        * For now, we don't return any features.
-        * In future, we might use features to return target
-        * specific features available for the preferred
-        * target type.
-        */
-       init->target = (__u32)target;
-
-       return 0;
-}
-
-int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
-{
-       return -EINVAL;
-}
-
-int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
-{
-       return -EINVAL;
-}
-
-int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
-                                 struct kvm_translation *tr)
-{
-       return -EINVAL;
-}
-
-int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
-                                       struct kvm_guest_debug *dbg)
-{
-       return -EINVAL;
-}
-
-int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr)
-{
-       int ret;
-
-       switch (attr->group) {
-       case KVM_ARM_VCPU_TIMER_CTRL:
-               ret = kvm_arm_timer_set_attr(vcpu, attr);
-               break;
-       default:
-               ret = -ENXIO;
-               break;
-       }
-
-       return ret;
-}
-
-int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr)
-{
-       int ret;
-
-       switch (attr->group) {
-       case KVM_ARM_VCPU_TIMER_CTRL:
-               ret = kvm_arm_timer_get_attr(vcpu, attr);
-               break;
-       default:
-               ret = -ENXIO;
-               break;
-       }
-
-       return ret;
-}
-
-int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
-                              struct kvm_device_attr *attr)
-{
-       int ret;
-
-       switch (attr->group) {
-       case KVM_ARM_VCPU_TIMER_CTRL:
-               ret = kvm_arm_timer_has_attr(vcpu, attr);
-               break;
-       default:
-               ret = -ENXIO;
-               break;
-       }
-
-       return ret;
-}
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
deleted file mode 100644 (file)
index e58a89d..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/kvm.h>
-#include <linux/kvm_host.h>
-#include <asm/kvm_emulate.h>
-#include <asm/kvm_coproc.h>
-#include <asm/kvm_mmu.h>
-#include <kvm/arm_hypercalls.h>
-#include <trace/events/kvm.h>
-
-#include "trace.h"
-
-typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
-
-static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       int ret;
-
-       trace_kvm_hvc(*vcpu_pc(vcpu), *vcpu_reg(vcpu, 0),
-                     kvm_vcpu_hvc_get_imm(vcpu));
-       vcpu->stat.hvc_exit_stat++;
-
-       ret = kvm_hvc_call_handler(vcpu);
-       if (ret < 0) {
-               vcpu_set_reg(vcpu, 0, ~0UL);
-               return 1;
-       }
-
-       return ret;
-}
-
-static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       /*
-        * "If an SMC instruction executed at Non-secure EL1 is
-        * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
-        * Trap exception, not a Secure Monitor Call exception [...]"
-        *
-        * We need to advance the PC after the trap, as it would
-        * otherwise return to the same address...
-        */
-       vcpu_set_reg(vcpu, 0, ~0UL);
-       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-       return 1;
-}
-
-/**
- * kvm_handle_wfx - handle a WFI or WFE instructions trapped in guests
- * @vcpu:      the vcpu pointer
- * @run:       the kvm_run structure pointer
- *
- * WFE: Yield the CPU and come back to this vcpu when the scheduler
- * decides to.
- * WFI: Simply call kvm_vcpu_block(), which will halt execution of
- * world-switches and schedule other host processes until there is an
- * incoming IRQ or FIQ to the VM.
- */
-static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       if (kvm_vcpu_get_hsr(vcpu) & HSR_WFI_IS_WFE) {
-               trace_kvm_wfx(*vcpu_pc(vcpu), true);
-               vcpu->stat.wfe_exit_stat++;
-               kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu));
-       } else {
-               trace_kvm_wfx(*vcpu_pc(vcpu), false);
-               vcpu->stat.wfi_exit_stat++;
-               kvm_vcpu_block(vcpu);
-               kvm_clear_request(KVM_REQ_UNHALT, vcpu);
-       }
-
-       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-
-       return 1;
-}
-
-static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       u32 hsr = kvm_vcpu_get_hsr(vcpu);
-
-       kvm_pr_unimpl("Unknown exception class: hsr: %#08x\n",
-                     hsr);
-
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
-static exit_handle_fn arm_exit_handlers[] = {
-       [0 ... HSR_EC_MAX]      = kvm_handle_unknown_ec,
-       [HSR_EC_WFI]            = kvm_handle_wfx,
-       [HSR_EC_CP15_32]        = kvm_handle_cp15_32,
-       [HSR_EC_CP15_64]        = kvm_handle_cp15_64,
-       [HSR_EC_CP14_MR]        = kvm_handle_cp14_32,
-       [HSR_EC_CP14_LS]        = kvm_handle_cp14_load_store,
-       [HSR_EC_CP14_64]        = kvm_handle_cp14_64,
-       [HSR_EC_CP_0_13]        = kvm_handle_cp_0_13_access,
-       [HSR_EC_CP10_ID]        = kvm_handle_cp10_id,
-       [HSR_EC_HVC]            = handle_hvc,
-       [HSR_EC_SMC]            = handle_smc,
-       [HSR_EC_IABT]           = kvm_handle_guest_abort,
-       [HSR_EC_DABT]           = kvm_handle_guest_abort,
-};
-
-static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
-{
-       u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
-
-       return arm_exit_handlers[hsr_ec];
-}
-
-/*
- * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
- * proper exit to userspace.
- */
-int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
-                      int exception_index)
-{
-       exit_handle_fn exit_handler;
-
-       if (ARM_ABORT_PENDING(exception_index)) {
-               u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
-
-               /*
-                * HVC/SMC already have an adjusted PC, which we need
-                * to correct in order to return to after having
-                * injected the abort.
-                */
-               if (hsr_ec == HSR_EC_HVC || hsr_ec == HSR_EC_SMC) {
-                       u32 adj =  kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
-                       *vcpu_pc(vcpu) -= adj;
-               }
-
-               kvm_inject_vabt(vcpu);
-               return 1;
-       }
-
-       exception_index = ARM_EXCEPTION_CODE(exception_index);
-
-       switch (exception_index) {
-       case ARM_EXCEPTION_IRQ:
-               return 1;
-       case ARM_EXCEPTION_HVC:
-               /*
-                * See ARM ARM B1.14.1: "Hyp traps on instructions
-                * that fail their condition code check"
-                */
-               if (!kvm_condition_valid(vcpu)) {
-                       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
-                       return 1;
-               }
-
-               exit_handler = kvm_get_exit_handler(vcpu);
-
-               return exit_handler(vcpu, run);
-       case ARM_EXCEPTION_DATA_ABORT:
-               kvm_inject_vabt(vcpu);
-               return 1;
-       case ARM_EXCEPTION_HYP_GONE:
-               /*
-                * HYP has been reset to the hyp-stub. This happens
-                * when a guest is pre-empted by kvm_reboot()'s
-                * shutdown call.
-                */
-               run->exit_reason = KVM_EXIT_FAIL_ENTRY;
-               return 0;
-       default:
-               kvm_pr_unimpl("Unsupported exception type: %d",
-                             exception_index);
-               run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
-               return 0;
-       }
-}
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
deleted file mode 100644 (file)
index ba88b1e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for Kernel-based Virtual Machine module, HYP part
-#
-
-ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING
-
-KVM=../../../../virt/kvm
-
-CFLAGS_ARMV7VE            :=$(call cc-option, -march=armv7ve)
-
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/aarch32.o
-
-obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
-obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += vfp.o
-obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o
-CFLAGS_banked-sr.o        += $(CFLAGS_ARMV7VE)
-
-obj-$(CONFIG_KVM_ARM_HOST) += entry.o
-obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
-obj-$(CONFIG_KVM_ARM_HOST) += switch.o
-CFLAGS_switch.o                   += $(CFLAGS_ARMV7VE)
-obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
-
-# KVM code is run at a different exception code with a different map, so
-# compiler instrumentation that inserts callbacks or checks into the code may
-# cause crashes. Just disable it.
-GCOV_PROFILE   := n
-KASAN_SANITIZE := n
-UBSAN_SANITIZE := n
-KCOV_INSTRUMENT        := n
diff --git a/arch/arm/kvm/hyp/banked-sr.c b/arch/arm/kvm/hyp/banked-sr.c
deleted file mode 100644 (file)
index c4632ed..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Original code:
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- *
- * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <asm/kvm_hyp.h>
-
-/*
- * gcc before 4.9 doesn't understand -march=armv7ve, so we have to
- * trick the assembler.
- */
-__asm__(".arch_extension     virt");
-
-void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt)
-{
-       ctxt->gp_regs.usr_regs.ARM_sp   = read_special(SP_usr);
-       ctxt->gp_regs.usr_regs.ARM_pc   = read_special(ELR_hyp);
-       ctxt->gp_regs.usr_regs.ARM_cpsr = read_special(SPSR);
-       ctxt->gp_regs.KVM_ARM_SVC_sp    = read_special(SP_svc);
-       ctxt->gp_regs.KVM_ARM_SVC_lr    = read_special(LR_svc);
-       ctxt->gp_regs.KVM_ARM_SVC_spsr  = read_special(SPSR_svc);
-       ctxt->gp_regs.KVM_ARM_ABT_sp    = read_special(SP_abt);
-       ctxt->gp_regs.KVM_ARM_ABT_lr    = read_special(LR_abt);
-       ctxt->gp_regs.KVM_ARM_ABT_spsr  = read_special(SPSR_abt);
-       ctxt->gp_regs.KVM_ARM_UND_sp    = read_special(SP_und);
-       ctxt->gp_regs.KVM_ARM_UND_lr    = read_special(LR_und);
-       ctxt->gp_regs.KVM_ARM_UND_spsr  = read_special(SPSR_und);
-       ctxt->gp_regs.KVM_ARM_IRQ_sp    = read_special(SP_irq);
-       ctxt->gp_regs.KVM_ARM_IRQ_lr    = read_special(LR_irq);
-       ctxt->gp_regs.KVM_ARM_IRQ_spsr  = read_special(SPSR_irq);
-       ctxt->gp_regs.KVM_ARM_FIQ_r8    = read_special(R8_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_r9    = read_special(R9_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_r10   = read_special(R10_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_fp    = read_special(R11_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_ip    = read_special(R12_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_sp    = read_special(SP_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_lr    = read_special(LR_fiq);
-       ctxt->gp_regs.KVM_ARM_FIQ_spsr  = read_special(SPSR_fiq);
-}
-
-void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt)
-{
-       write_special(ctxt->gp_regs.usr_regs.ARM_sp,    SP_usr);
-       write_special(ctxt->gp_regs.usr_regs.ARM_pc,    ELR_hyp);
-       write_special(ctxt->gp_regs.usr_regs.ARM_cpsr,  SPSR_cxsf);
-       write_special(ctxt->gp_regs.KVM_ARM_SVC_sp,     SP_svc);
-       write_special(ctxt->gp_regs.KVM_ARM_SVC_lr,     LR_svc);
-       write_special(ctxt->gp_regs.KVM_ARM_SVC_spsr,   SPSR_svc);
-       write_special(ctxt->gp_regs.KVM_ARM_ABT_sp,     SP_abt);
-       write_special(ctxt->gp_regs.KVM_ARM_ABT_lr,     LR_abt);
-       write_special(ctxt->gp_regs.KVM_ARM_ABT_spsr,   SPSR_abt);
-       write_special(ctxt->gp_regs.KVM_ARM_UND_sp,     SP_und);
-       write_special(ctxt->gp_regs.KVM_ARM_UND_lr,     LR_und);
-       write_special(ctxt->gp_regs.KVM_ARM_UND_spsr,   SPSR_und);
-       write_special(ctxt->gp_regs.KVM_ARM_IRQ_sp,     SP_irq);
-       write_special(ctxt->gp_regs.KVM_ARM_IRQ_lr,     LR_irq);
-       write_special(ctxt->gp_regs.KVM_ARM_IRQ_spsr,   SPSR_irq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r8,     R8_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r9,     R9_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r10,    R10_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_fp,     R11_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_ip,     R12_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_sp,     SP_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_lr,     LR_fiq);
-       write_special(ctxt->gp_regs.KVM_ARM_FIQ_spsr,   SPSR_fiq);
-}
diff --git a/arch/arm/kvm/hyp/cp15-sr.c b/arch/arm/kvm/hyp/cp15-sr.c
deleted file mode 100644 (file)
index e692330..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Original code:
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- *
- * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <asm/kvm_hyp.h>
-
-static u64 *cp15_64(struct kvm_cpu_context *ctxt, int idx)
-{
-       return (u64 *)(ctxt->cp15 + idx);
-}
-
-void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
-{
-       ctxt->cp15[c0_CSSELR]           = read_sysreg(CSSELR);
-       ctxt->cp15[c1_SCTLR]            = read_sysreg(SCTLR);
-       ctxt->cp15[c1_CPACR]            = read_sysreg(CPACR);
-       *cp15_64(ctxt, c2_TTBR0)        = read_sysreg(TTBR0);
-       *cp15_64(ctxt, c2_TTBR1)        = read_sysreg(TTBR1);
-       ctxt->cp15[c2_TTBCR]            = read_sysreg(TTBCR);
-       ctxt->cp15[c3_DACR]             = read_sysreg(DACR);
-       ctxt->cp15[c5_DFSR]             = read_sysreg(DFSR);
-       ctxt->cp15[c5_IFSR]             = read_sysreg(IFSR);
-       ctxt->cp15[c5_ADFSR]            = read_sysreg(ADFSR);
-       ctxt->cp15[c5_AIFSR]            = read_sysreg(AIFSR);
-       ctxt->cp15[c6_DFAR]             = read_sysreg(DFAR);
-       ctxt->cp15[c6_IFAR]             = read_sysreg(IFAR);
-       *cp15_64(ctxt, c7_PAR)          = read_sysreg(PAR);
-       ctxt->cp15[c10_PRRR]            = read_sysreg(PRRR);
-       ctxt->cp15[c10_NMRR]            = read_sysreg(NMRR);
-       ctxt->cp15[c10_AMAIR0]          = read_sysreg(AMAIR0);
-       ctxt->cp15[c10_AMAIR1]          = read_sysreg(AMAIR1);
-       ctxt->cp15[c12_VBAR]            = read_sysreg(VBAR);
-       ctxt->cp15[c13_CID]             = read_sysreg(CID);
-       ctxt->cp15[c13_TID_URW]         = read_sysreg(TID_URW);
-       ctxt->cp15[c13_TID_URO]         = read_sysreg(TID_URO);
-       ctxt->cp15[c13_TID_PRIV]        = read_sysreg(TID_PRIV);
-       ctxt->cp15[c14_CNTKCTL]         = read_sysreg(CNTKCTL);
-}
-
-void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
-{
-       write_sysreg(ctxt->cp15[c0_MPIDR],      VMPIDR);
-       write_sysreg(ctxt->cp15[c0_CSSELR],     CSSELR);
-       write_sysreg(ctxt->cp15[c1_SCTLR],      SCTLR);
-       write_sysreg(ctxt->cp15[c1_CPACR],      CPACR);
-       write_sysreg(*cp15_64(ctxt, c2_TTBR0),  TTBR0);
-       write_sysreg(*cp15_64(ctxt, c2_TTBR1),  TTBR1);
-       write_sysreg(ctxt->cp15[c2_TTBCR],      TTBCR);
-       write_sysreg(ctxt->cp15[c3_DACR],       DACR);
-       write_sysreg(ctxt->cp15[c5_DFSR],       DFSR);
-       write_sysreg(ctxt->cp15[c5_IFSR],       IFSR);
-       write_sysreg(ctxt->cp15[c5_ADFSR],      ADFSR);
-       write_sysreg(ctxt->cp15[c5_AIFSR],      AIFSR);
-       write_sysreg(ctxt->cp15[c6_DFAR],       DFAR);
-       write_sysreg(ctxt->cp15[c6_IFAR],       IFAR);
-       write_sysreg(*cp15_64(ctxt, c7_PAR),    PAR);
-       write_sysreg(ctxt->cp15[c10_PRRR],      PRRR);
-       write_sysreg(ctxt->cp15[c10_NMRR],      NMRR);
-       write_sysreg(ctxt->cp15[c10_AMAIR0],    AMAIR0);
-       write_sysreg(ctxt->cp15[c10_AMAIR1],    AMAIR1);
-       write_sysreg(ctxt->cp15[c12_VBAR],      VBAR);
-       write_sysreg(ctxt->cp15[c13_CID],       CID);
-       write_sysreg(ctxt->cp15[c13_TID_URW],   TID_URW);
-       write_sysreg(ctxt->cp15[c13_TID_URO],   TID_URO);
-       write_sysreg(ctxt->cp15[c13_TID_PRIV],  TID_PRIV);
-       write_sysreg(ctxt->cp15[c14_CNTKCTL],   CNTKCTL);
-}
diff --git a/arch/arm/kvm/hyp/entry.S b/arch/arm/kvm/hyp/entry.S
deleted file mode 100644 (file)
index 4bd1f6a..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2016 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
-*/
-
-#include <linux/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_asm.h>
-
-       .arch_extension     virt
-
-       .text
-       .pushsection    .hyp.text, "ax"
-
-#define USR_REGS_OFFSET                (CPU_CTXT_GP_REGS + GP_REGS_USR)
-
-/* int __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host) */
-ENTRY(__guest_enter)
-       @ Save host registers
-       add     r1, r1, #(USR_REGS_OFFSET + S_R4)
-       stm     r1!, {r4-r12}
-       str     lr, [r1, #4]    @ Skip SP_usr (already saved)
-
-       @ Restore guest registers
-       add     r0, r0,  #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
-       ldr     lr, [r0, #S_LR]
-       ldm     r0, {r0-r12}
-
-       clrex
-       eret
-ENDPROC(__guest_enter)
-
-ENTRY(__guest_exit)
-       /*
-        * return convention:
-        * guest r0, r1, r2 saved on the stack
-        * r0: vcpu pointer
-        * r1: exception code
-        */
-
-       add     r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R3)
-       stm     r2!, {r3-r12}
-       str     lr, [r2, #4]
-       add     r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
-       pop     {r3, r4, r5}            @ r0, r1, r2
-       stm     r2, {r3-r5}
-
-       ldr     r0, [r0, #VCPU_HOST_CTXT]
-       add     r0, r0, #(USR_REGS_OFFSET + S_R4)
-       ldm     r0!, {r4-r12}
-       ldr     lr, [r0, #4]
-
-       mov     r0, r1
-       mrs     r1, SPSR
-       mrs     r2, ELR_hyp
-       mrc     p15, 4, r3, c5, c2, 0   @ HSR
-
-       /*
-        * Force loads and stores to complete before unmasking aborts
-        * and forcing the delivery of the exception. This gives us a
-        * single instruction window, which the handler will try to
-        * match.
-        */
-       dsb     sy
-       cpsie   a
-
-       .global abort_guest_exit_start
-abort_guest_exit_start:
-
-       isb
-
-       .global abort_guest_exit_end
-abort_guest_exit_end:
-
-       /*
-        * If we took an abort, r0[31] will be set, and cmp will set
-        * the N bit in PSTATE.
-        */
-       cmp     r0, #0
-       msrmi   SPSR_cxsf, r1
-       msrmi   ELR_hyp, r2
-       mcrmi   p15, 4, r3, c5, c2, 0   @ HSR
-
-       bx      lr
-ENDPROC(__guest_exit)
-
-/*
- * If VFPv3 support is not available, then we will not switch the VFP
- * registers; however cp10 and cp11 accesses will still trap and fallback
- * to the regular coprocessor emulation code, which currently will
- * inject an undefined exception to the guest.
- */
-#ifdef CONFIG_VFPv3
-ENTRY(__vfp_guest_restore)
-       push    {r3, r4, lr}
-
-       @ NEON/VFP used.  Turn on VFP access.
-       mrc     p15, 4, r1, c1, c1, 2           @ HCPTR
-       bic     r1, r1, #(HCPTR_TCP(10) | HCPTR_TCP(11))
-       mcr     p15, 4, r1, c1, c1, 2           @ HCPTR
-       isb
-
-       @ Switch VFP/NEON hardware state to the guest's
-       mov     r4, r0
-       ldr     r0, [r0, #VCPU_HOST_CTXT]
-       add     r0, r0, #CPU_CTXT_VFP
-       bl      __vfp_save_state
-       add     r0, r4, #(VCPU_GUEST_CTXT + CPU_CTXT_VFP)
-       bl      __vfp_restore_state
-
-       pop     {r3, r4, lr}
-       pop     {r0, r1, r2}
-       clrex
-       eret
-ENDPROC(__vfp_guest_restore)
-#endif
-
-       .popsection
-
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
deleted file mode 100644 (file)
index fe3d781..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/arm-smccc.h>
-#include <linux/linkage.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_asm.h>
-
-       .arch_extension     virt
-
-       .text
-       .pushsection    .hyp.text, "ax"
-
-.macro load_vcpu       reg
-       mrc     p15, 4, \reg, c13, c0, 2        @ HTPIDR
-.endm
-
-/********************************************************************
- * Hypervisor exception vector and handlers
- *
- *
- * The KVM/ARM Hypervisor ABI is defined as follows:
- *
- * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
- * instruction is issued since all traps are disabled when running the host
- * kernel as per the Hyp-mode initialization at boot time.
- *
- * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
- * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
- * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
- * instructions are called from within Hyp-mode.
- *
- * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
- *    Switching to Hyp mode is done through a simple HVC #0 instruction. The
- *    exception vector code will check that the HVC comes from VMID==0.
- *    - r0 contains a pointer to a HYP function
- *    - r1, r2, and r3 contain arguments to the above function.
- *    - The HYP function will be called with its arguments in r0, r1 and r2.
- *    On HYP function return, we return directly to SVC.
- *
- * Note that the above is used to execute code in Hyp-mode from a host-kernel
- * point of view, and is a different concept from performing a world-switch and
- * executing guest code SVC mode (with a VMID != 0).
- */
-
-       .align 5
-__kvm_hyp_vector:
-       .global __kvm_hyp_vector
-
-       @ Hyp-mode exception vector
-       W(b)    hyp_reset
-       W(b)    hyp_undef
-       W(b)    hyp_svc
-       W(b)    hyp_pabt
-       W(b)    hyp_dabt
-       W(b)    hyp_hvc
-       W(b)    hyp_irq
-       W(b)    hyp_fiq
-
-#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
-       .align 5
-__kvm_hyp_vector_ic_inv:
-       .global __kvm_hyp_vector_ic_inv
-
-       /*
-        * We encode the exception entry in the bottom 3 bits of
-        * SP, and we have to guarantee to be 8 bytes aligned.
-        */
-       W(add)  sp, sp, #1      /* Reset          7 */
-       W(add)  sp, sp, #1      /* Undef          6 */
-       W(add)  sp, sp, #1      /* Syscall        5 */
-       W(add)  sp, sp, #1      /* Prefetch abort 4 */
-       W(add)  sp, sp, #1      /* Data abort     3 */
-       W(add)  sp, sp, #1      /* HVC            2 */
-       W(add)  sp, sp, #1      /* IRQ            1 */
-       W(nop)                  /* FIQ            0 */
-
-       mcr     p15, 0, r0, c7, c5, 0   /* ICIALLU */
-       isb
-
-       b       decode_vectors
-
-       .align 5
-__kvm_hyp_vector_bp_inv:
-       .global __kvm_hyp_vector_bp_inv
-
-       /*
-        * We encode the exception entry in the bottom 3 bits of
-        * SP, and we have to guarantee to be 8 bytes aligned.
-        */
-       W(add)  sp, sp, #1      /* Reset          7 */
-       W(add)  sp, sp, #1      /* Undef          6 */
-       W(add)  sp, sp, #1      /* Syscall        5 */
-       W(add)  sp, sp, #1      /* Prefetch abort 4 */
-       W(add)  sp, sp, #1      /* Data abort     3 */
-       W(add)  sp, sp, #1      /* HVC            2 */
-       W(add)  sp, sp, #1      /* IRQ            1 */
-       W(nop)                  /* FIQ            0 */
-
-       mcr     p15, 0, r0, c7, c5, 6   /* BPIALL */
-       isb
-
-decode_vectors:
-
-#ifdef CONFIG_THUMB2_KERNEL
-       /*
-        * Yet another silly hack: Use VPIDR as a temp register.
-        * Thumb2 is really a pain, as SP cannot be used with most
-        * of the bitwise instructions. The vect_br macro ensures
-        * things gets cleaned-up.
-        */
-       mcr     p15, 4, r0, c0, c0, 0   /* VPIDR */
-       mov     r0, sp
-       and     r0, r0, #7
-       sub     sp, sp, r0
-       push    {r1, r2}
-       mov     r1, r0
-       mrc     p15, 4, r0, c0, c0, 0   /* VPIDR */
-       mrc     p15, 0, r2, c0, c0, 0   /* MIDR  */
-       mcr     p15, 4, r2, c0, c0, 0   /* VPIDR */
-#endif
-
-.macro vect_br val, targ
-ARM(   eor     sp, sp, #\val   )
-ARM(   tst     sp, #7          )
-ARM(   eorne   sp, sp, #\val   )
-
-THUMB( cmp     r1, #\val       )
-THUMB( popeq   {r1, r2}        )
-
-       beq     \targ
-.endm
-
-       vect_br 0, hyp_fiq
-       vect_br 1, hyp_irq
-       vect_br 2, hyp_hvc
-       vect_br 3, hyp_dabt
-       vect_br 4, hyp_pabt
-       vect_br 5, hyp_svc
-       vect_br 6, hyp_undef
-       vect_br 7, hyp_reset
-#endif
-
-.macro invalid_vector label, cause
-       .align
-\label:        mov     r0, #\cause
-       b       __hyp_panic
-.endm
-
-       invalid_vector  hyp_reset       ARM_EXCEPTION_RESET
-       invalid_vector  hyp_undef       ARM_EXCEPTION_UNDEFINED
-       invalid_vector  hyp_svc         ARM_EXCEPTION_SOFTWARE
-       invalid_vector  hyp_pabt        ARM_EXCEPTION_PREF_ABORT
-       invalid_vector  hyp_fiq         ARM_EXCEPTION_FIQ
-
-ENTRY(__hyp_do_panic)
-       mrs     lr, cpsr
-       bic     lr, lr, #MODE_MASK
-       orr     lr, lr, #SVC_MODE
-THUMB( orr     lr, lr, #PSR_T_BIT      )
-       msr     spsr_cxsf, lr
-       ldr     lr, =panic
-       msr     ELR_hyp, lr
-       ldr     lr, =__kvm_call_hyp
-       clrex
-       eret
-ENDPROC(__hyp_do_panic)
-
-hyp_hvc:
-       /*
-        * Getting here is either because of a trap from a guest,
-        * or from executing HVC from the host kernel, which means
-        * "do something in Hyp mode".
-        */
-       push    {r0, r1, r2}
-
-       @ Check syndrome register
-       mrc     p15, 4, r1, c5, c2, 0   @ HSR
-       lsr     r0, r1, #HSR_EC_SHIFT
-       cmp     r0, #HSR_EC_HVC
-       bne     guest_trap              @ Not HVC instr.
-
-       /*
-        * Let's check if the HVC came from VMID 0 and allow simple
-        * switch to Hyp mode
-        */
-       mrrc    p15, 6, r0, r2, c2
-       lsr     r2, r2, #16
-       and     r2, r2, #0xff
-       cmp     r2, #0
-       bne     guest_hvc_trap          @ Guest called HVC
-
-       /*
-        * Getting here means host called HVC, we shift parameters and branch
-        * to Hyp function.
-        */
-       pop     {r0, r1, r2}
-
-       /*
-        * Check if we have a kernel function, which is guaranteed to be
-        * bigger than the maximum hyp stub hypercall
-        */
-       cmp     r0, #HVC_STUB_HCALL_NR
-       bhs     1f
-
-       /*
-        * Not a kernel function, treat it as a stub hypercall.
-        * Compute the physical address for __kvm_handle_stub_hvc
-        * (as the code lives in the idmaped page) and branch there.
-        * We hijack ip (r12) as a tmp register.
-        */
-       push    {r1}
-       ldr     r1, =kimage_voffset
-       ldr     r1, [r1]
-       ldr     ip, =__kvm_handle_stub_hvc
-       sub     ip, ip, r1
-       pop     {r1}
-
-       bx      ip
-
-1:
-       /*
-        * Pushing r2 here is just a way of keeping the stack aligned to
-        * 8 bytes on any path that can trigger a HYP exception. Here,
-        * we may well be about to jump into the guest, and the guest
-        * exit would otherwise be badly decoded by our fancy
-        * "decode-exception-without-a-branch" code...
-        */
-       push    {r2, lr}
-
-       mov     lr, r0
-       mov     r0, r1
-       mov     r1, r2
-       mov     r2, r3
-
-THUMB( orr     lr, #1)
-       blx     lr                      @ Call the HYP function
-
-       pop     {r2, lr}
-       eret
-
-guest_hvc_trap:
-       movw    r2, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1
-       movt    r2, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1
-       ldr     r0, [sp]                @ Guest's r0
-       teq     r0, r2
-       bne     guest_trap
-       add     sp, sp, #12
-       @ Returns:
-       @ r0 = 0
-       @ r1 = HSR value (perfectly predictable)
-       @ r2 = ARM_SMCCC_ARCH_WORKAROUND_1
-       mov     r0, #0
-       eret
-
-guest_trap:
-       load_vcpu r0                    @ Load VCPU pointer to r0
-
-#ifdef CONFIG_VFPv3
-       @ Check for a VFP access
-       lsr     r1, r1, #HSR_EC_SHIFT
-       cmp     r1, #HSR_EC_CP_0_13
-       beq     __vfp_guest_restore
-#endif
-
-       mov     r1, #ARM_EXCEPTION_HVC
-       b       __guest_exit
-
-hyp_irq:
-       push    {r0, r1, r2}
-       mov     r1, #ARM_EXCEPTION_IRQ
-       load_vcpu r0                    @ Load VCPU pointer to r0
-       b       __guest_exit
-
-hyp_dabt:
-       push    {r0, r1}
-       mrs     r0, ELR_hyp
-       ldr     r1, =abort_guest_exit_start
-THUMB( add     r1, r1, #1)
-       cmp     r0, r1
-       ldrne   r1, =abort_guest_exit_end
-THUMB( addne   r1, r1, #1)
-       cmpne   r0, r1
-       pop     {r0, r1}
-       bne     __hyp_panic
-
-       orr     r0, r0, #(1 << ARM_EXIT_WITH_ABORT_BIT)
-       eret
-
-       .ltorg
-
-       .popsection
diff --git a/arch/arm/kvm/hyp/s2-setup.c b/arch/arm/kvm/hyp/s2-setup.c
deleted file mode 100644 (file)
index 5dfbea5..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2016 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <linux/types.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_asm.h>
-#include <asm/kvm_hyp.h>
-
-void __hyp_text __init_stage2_translation(void)
-{
-       u64 val;
-
-       val = read_sysreg(VTCR) & ~VTCR_MASK;
-
-       val |= read_sysreg(HTCR) & VTCR_HTCR_SH;
-       val |= KVM_VTCR_SL0 | KVM_VTCR_T0SZ | KVM_VTCR_S;
-
-       write_sysreg(val, VTCR);
-}
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
deleted file mode 100644 (file)
index 1efeef3..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.com>
- */
-#include <linux/jump_label.h>
-
-#include <asm/kvm_asm.h>
-#include <asm/kvm_hyp.h>
-#include <asm/kvm_mmu.h>
-
-__asm__(".arch_extension     virt");
-
-/*
- * Activate the traps, saving the host's fpexc register before
- * overwriting it. We'll restore it on VM exit.
- */
-static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
-{
-       u32 val;
-
-       /*
-        * We are about to set HCPTR.TCP10/11 to trap all floating point
-        * register accesses to HYP, however, the ARM ARM clearly states that
-        * traps are only taken to HYP if the operation would not otherwise
-        * trap to SVC.  Therefore, always make sure that for 32-bit guests,
-        * we set FPEXC.EN to prevent traps to SVC, when setting the TCP bits.
-        */
-       val = read_sysreg(VFP_FPEXC);
-       *fpexc_host = val;
-       if (!(val & FPEXC_EN)) {
-               write_sysreg(val | FPEXC_EN, VFP_FPEXC);
-               isb();
-       }
-
-       write_sysreg(vcpu->arch.hcr, HCR);
-       /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
-       write_sysreg(HSTR_T(15), HSTR);
-       write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
-       val = read_sysreg(HDCR);
-       val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */
-       val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */
-       write_sysreg(val, HDCR);
-}
-
-static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
-{
-       u32 val;
-
-       /*
-        * If we pended a virtual abort, preserve it until it gets
-        * cleared. See B1.9.9 (Virtual Abort exception) for details,
-        * but the crucial bit is the zeroing of HCR.VA in the
-        * pseudocode.
-        */
-       if (vcpu->arch.hcr & HCR_VA)
-               vcpu->arch.hcr = read_sysreg(HCR);
-
-       write_sysreg(0, HCR);
-       write_sysreg(0, HSTR);
-       val = read_sysreg(HDCR);
-       write_sysreg(val & ~(HDCR_TPM | HDCR_TPMCR), HDCR);
-       write_sysreg(0, HCPTR);
-}
-
-static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
-       write_sysreg(vcpu->arch.midr, VPIDR);
-}
-
-static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
-{
-       write_sysreg(0, VTTBR);
-       write_sysreg(read_sysreg(MIDR), VPIDR);
-}
-
-
-static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu)
-{
-       if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) {
-               __vgic_v3_save_state(vcpu);
-               __vgic_v3_deactivate_traps(vcpu);
-       }
-}
-
-static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
-{
-       if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) {
-               __vgic_v3_activate_traps(vcpu);
-               __vgic_v3_restore_state(vcpu);
-       }
-}
-
-static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
-{
-       u32 hsr = read_sysreg(HSR);
-       u8 ec = hsr >> HSR_EC_SHIFT;
-       u32 hpfar, far;
-
-       vcpu->arch.fault.hsr = hsr;
-
-       if (ec == HSR_EC_IABT)
-               far = read_sysreg(HIFAR);
-       else if (ec == HSR_EC_DABT)
-               far = read_sysreg(HDFAR);
-       else
-               return true;
-
-       /*
-        * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
-        *
-        * Abort on the stage 2 translation for a memory access from a
-        * Non-secure PL1 or PL0 mode:
-        *
-        * For any Access flag fault or Translation fault, and also for any
-        * Permission fault on the stage 2 translation of a memory access
-        * made as part of a translation table walk for a stage 1 translation,
-        * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
-        * is UNKNOWN.
-        */
-       if (!(hsr & HSR_DABT_S1PTW) && (hsr & HSR_FSC_TYPE) == FSC_PERM) {
-               u64 par, tmp;
-
-               par = read_sysreg(PAR);
-               write_sysreg(far, ATS1CPR);
-               isb();
-
-               tmp = read_sysreg(PAR);
-               write_sysreg(par, PAR);
-
-               if (unlikely(tmp & 1))
-                       return false; /* Translation failed, back to guest */
-
-               hpfar = ((tmp >> 12) & ((1UL << 28) - 1)) << 4;
-       } else {
-               hpfar = read_sysreg(HPFAR);
-       }
-
-       vcpu->arch.fault.hxfar = far;
-       vcpu->arch.fault.hpfar = hpfar;
-       return true;
-}
-
-int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
-{
-       struct kvm_cpu_context *host_ctxt;
-       struct kvm_cpu_context *guest_ctxt;
-       bool fp_enabled;
-       u64 exit_code;
-       u32 fpexc;
-
-       vcpu = kern_hyp_va(vcpu);
-       write_sysreg(vcpu, HTPIDR);
-
-       host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
-       guest_ctxt = &vcpu->arch.ctxt;
-
-       __sysreg_save_state(host_ctxt);
-       __banked_save_state(host_ctxt);
-
-       __activate_traps(vcpu, &fpexc);
-       __activate_vm(vcpu);
-
-       __vgic_restore_state(vcpu);
-       __timer_enable_traps(vcpu);
-
-       __sysreg_restore_state(guest_ctxt);
-       __banked_restore_state(guest_ctxt);
-
-       /* Jump in the fire! */
-again:
-       exit_code = __guest_enter(vcpu, host_ctxt);
-       /* And we're baaack! */
-
-       if (exit_code == ARM_EXCEPTION_HVC && !__populate_fault_info(vcpu))
-               goto again;
-
-       fp_enabled = __vfp_enabled();
-
-       __banked_save_state(guest_ctxt);
-       __sysreg_save_state(guest_ctxt);
-       __timer_disable_traps(vcpu);
-
-       __vgic_save_state(vcpu);
-
-       __deactivate_traps(vcpu);
-       __deactivate_vm(vcpu);
-
-       __banked_restore_state(host_ctxt);
-       __sysreg_restore_state(host_ctxt);
-
-       if (fp_enabled) {
-               __vfp_save_state(&guest_ctxt->vfp);
-               __vfp_restore_state(&host_ctxt->vfp);
-       }
-
-       write_sysreg(fpexc, VFP_FPEXC);
-
-       return exit_code;
-}
-
-static const char * const __hyp_panic_string[] = {
-       [ARM_EXCEPTION_RESET]      = "\nHYP panic: RST   PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_UNDEFINED]  = "\nHYP panic: UNDEF PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_SOFTWARE]   = "\nHYP panic: SVC   PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_PREF_ABORT] = "\nHYP panic: PABRT PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_DATA_ABORT] = "\nHYP panic: DABRT PC:%08x ADDR:%08x",
-       [ARM_EXCEPTION_IRQ]        = "\nHYP panic: IRQ   PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_FIQ]        = "\nHYP panic: FIQ   PC:%08x CPSR:%08x",
-       [ARM_EXCEPTION_HVC]        = "\nHYP panic: HVC   PC:%08x CPSR:%08x",
-};
-
-void __hyp_text __noreturn __hyp_panic(int cause)
-{
-       u32 elr = read_special(ELR_hyp);
-       u32 val;
-
-       if (cause == ARM_EXCEPTION_DATA_ABORT)
-               val = read_sysreg(HDFAR);
-       else
-               val = read_special(SPSR);
-
-       if (read_sysreg(VTTBR)) {
-               struct kvm_vcpu *vcpu;
-               struct kvm_cpu_context *host_ctxt;
-
-               vcpu = (struct kvm_vcpu *)read_sysreg(HTPIDR);
-               host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
-               __timer_disable_traps(vcpu);
-               __deactivate_traps(vcpu);
-               __deactivate_vm(vcpu);
-               __banked_restore_state(host_ctxt);
-               __sysreg_restore_state(host_ctxt);
-       }
-
-       /* Call panic for real */
-       __hyp_do_panic(__hyp_panic_string[cause], elr, val);
-
-       unreachable();
-}
diff --git a/arch/arm/kvm/hyp/tlb.c b/arch/arm/kvm/hyp/tlb.c
deleted file mode 100644 (file)
index 848f27b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Original code:
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- *
- * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com>
- */
-
-#include <asm/kvm_hyp.h>
-#include <asm/kvm_mmu.h>
-
-/**
- * Flush per-VMID TLBs
- *
- * __kvm_tlb_flush_vmid(struct kvm *kvm);
- *
- * We rely on the hardware to broadcast the TLB invalidation to all CPUs
- * inside the inner-shareable domain (which is the case for all v7
- * implementations).  If we come across a non-IS SMP implementation, we'll
- * have to use an IPI based mechanism. Until then, we stick to the simple
- * hardware assisted version.
- *
- * As v7 does not support flushing per IPA, just nuke the whole TLB
- * instead, ignoring the ipa value.
- */
-void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
-{
-       dsb(ishst);
-
-       /* Switch to requested VMID */
-       kvm = kern_hyp_va(kvm);
-       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
-       isb();
-
-       write_sysreg(0, TLBIALLIS);
-       dsb(ish);
-       isb();
-
-       write_sysreg(0, VTTBR);
-}
-
-void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
-{
-       __kvm_tlb_flush_vmid(kvm);
-}
-
-void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
-
-       /* Switch to requested VMID */
-       write_sysreg(kvm_get_vttbr(kvm), VTTBR);
-       isb();
-
-       write_sysreg(0, TLBIALL);
-       dsb(nsh);
-       isb();
-
-       write_sysreg(0, VTTBR);
-}
-
-void __hyp_text __kvm_flush_vm_context(void)
-{
-       write_sysreg(0, TLBIALLNSNHIS);
-       write_sysreg(0, ICIALLUIS);
-       dsb(ish);
-}
diff --git a/arch/arm/kvm/hyp/vfp.S b/arch/arm/kvm/hyp/vfp.S
deleted file mode 100644 (file)
index 675a523..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/linkage.h>
-#include <asm/vfpmacros.h>
-
-       .text
-       .pushsection    .hyp.text, "ax"
-
-/* void __vfp_save_state(struct vfp_hard_struct *vfp); */
-ENTRY(__vfp_save_state)
-       push    {r4, r5}
-       VFPFMRX r1, FPEXC
-
-       @ Make sure *really* VFP is enabled so we can touch the registers.
-       orr     r5, r1, #FPEXC_EN
-       tst     r5, #FPEXC_EX           @ Check for VFP Subarchitecture
-       bic     r5, r5, #FPEXC_EX       @ FPEXC_EX disable
-       VFPFMXR FPEXC, r5
-       isb
-
-       VFPFMRX r2, FPSCR
-       beq     1f
-
-       @ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
-       @ we only need to save them if FPEXC_EX is set.
-       VFPFMRX r3, FPINST
-       tst     r5, #FPEXC_FP2V
-       VFPFMRX r4, FPINST2, ne         @ vmrsne
-1:
-       VFPFSTMIA r0, r5                @ Save VFP registers
-       stm     r0, {r1-r4}             @ Save FPEXC, FPSCR, FPINST, FPINST2
-       pop     {r4, r5}
-       bx      lr
-ENDPROC(__vfp_save_state)
-
-/* void __vfp_restore_state(struct vfp_hard_struct *vfp);
- * Assume FPEXC_EN is on and FPEXC_EX is off */
-ENTRY(__vfp_restore_state)
-       VFPFLDMIA r0, r1                @ Load VFP registers
-       ldm     r0, {r0-r3}             @ Load FPEXC, FPSCR, FPINST, FPINST2
-
-       VFPFMXR FPSCR, r1
-       tst     r0, #FPEXC_EX           @ Check for VFP Subarchitecture
-       beq     1f
-       VFPFMXR FPINST, r2
-       tst     r0, #FPEXC_FP2V
-       VFPFMXR FPINST2, r3, ne
-1:
-       VFPFMXR FPEXC, r0               @ FPEXC (last, in case !EN)
-       bx      lr
-ENDPROC(__vfp_restore_state)
-
-       .popsection
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
deleted file mode 100644 (file)
index 33e34b6..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/unified.h>
-#include <asm/asm-offsets.h>
-#include <asm/kvm_asm.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_mmu.h>
-#include <asm/virt.h>
-
-/********************************************************************
- * Hypervisor initialization
- *   - should be called with:
- *       r0 = top of Hyp stack (kernel VA)
- *       r1 = pointer to hyp vectors
- *       r2,r3 = Hypervisor pgd pointer
- *
- * The init scenario is:
- * - We jump in HYP with 3 parameters: runtime HYP pgd, runtime stack,
- *   runtime vectors
- * - Invalidate TLBs
- * - Set stack and vectors
- * - Setup the page tables
- * - Enable the MMU
- * - Profit! (or eret, if you only care about the code).
- *
- * Another possibility is to get a HYP stub hypercall.
- * We discriminate between the two by checking if r0 contains a value
- * that is less than HVC_STUB_HCALL_NR.
- */
-
-       .text
-       .pushsection    .hyp.idmap.text,"ax"
-       .align 5
-__kvm_hyp_init:
-       .globl __kvm_hyp_init
-
-       @ Hyp-mode exception vector
-       W(b)    .
-       W(b)    .
-       W(b)    .
-       W(b)    .
-       W(b)    .
-       W(b)    __do_hyp_init
-       W(b)    .
-       W(b)    .
-
-__do_hyp_init:
-       @ Check for a stub hypercall
-       cmp     r0, #HVC_STUB_HCALL_NR
-       blo     __kvm_handle_stub_hvc
-
-       @ Set stack pointer
-       mov     sp, r0
-
-       @ Set HVBAR to point to the HYP vectors
-       mcr     p15, 4, r1, c12, c0, 0  @ HVBAR
-
-       @ Set the HTTBR to point to the hypervisor PGD pointer passed
-       mcrr    p15, 4, rr_lo_hi(r2, r3), c2
-
-       @ Set the HTCR and VTCR to the same shareability and cacheability
-       @ settings as the non-secure TTBCR and with T0SZ == 0.
-       mrc     p15, 4, r0, c2, c0, 2   @ HTCR
-       ldr     r2, =HTCR_MASK
-       bic     r0, r0, r2
-       mrc     p15, 0, r1, c2, c0, 2   @ TTBCR
-       and     r1, r1, #(HTCR_MASK & ~TTBCR_T0SZ)
-       orr     r0, r0, r1
-       mcr     p15, 4, r0, c2, c0, 2   @ HTCR
-
-       @ Use the same memory attributes for hyp. accesses as the kernel
-       @ (copy MAIRx ro HMAIRx).
-       mrc     p15, 0, r0, c10, c2, 0
-       mcr     p15, 4, r0, c10, c2, 0
-       mrc     p15, 0, r0, c10, c2, 1
-       mcr     p15, 4, r0, c10, c2, 1
-
-       @ Invalidate the stale TLBs from Bootloader
-       mcr     p15, 4, r0, c8, c7, 0   @ TLBIALLH
-       dsb     ish
-
-       @ Set the HSCTLR to:
-       @  - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
-       @  - Endianness: Kernel config
-       @  - Fast Interrupt Features: Kernel config
-       @  - Write permission implies XN: disabled
-       @  - Instruction cache: enabled
-       @  - Data/Unified cache: enabled
-       @  - MMU: enabled (this code must be run from an identity mapping)
-       mrc     p15, 4, r0, c1, c0, 0   @ HSCR
-       ldr     r2, =HSCTLR_MASK
-       bic     r0, r0, r2
-       mrc     p15, 0, r1, c1, c0, 0   @ SCTLR
-       ldr     r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
-       and     r1, r1, r2
- ARM(  ldr     r2, =(HSCTLR_M)                                 )
- THUMB(        ldr     r2, =(HSCTLR_M | HSCTLR_TE)                     )
-       orr     r1, r1, r2
-       orr     r0, r0, r1
-       mcr     p15, 4, r0, c1, c0, 0   @ HSCR
-       isb
-
-       eret
-
-ENTRY(__kvm_handle_stub_hvc)
-       cmp     r0, #HVC_SOFT_RESTART
-       bne     1f
-
-       /* The target is expected in r1 */
-       msr     ELR_hyp, r1
-       mrs     r0, cpsr
-       bic     r0, r0, #MODE_MASK
-       orr     r0, r0, #HYP_MODE
-THUMB( orr     r0, r0, #PSR_T_BIT      )
-       msr     spsr_cxsf, r0
-       b       reset
-
-1:     cmp     r0, #HVC_RESET_VECTORS
-       bne     1f
-
-reset:
-       /* We're now in idmap, disable MMU */
-       mrc     p15, 4, r1, c1, c0, 0   @ HSCTLR
-       ldr     r0, =(HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I)
-       bic     r1, r1, r0
-       mcr     p15, 4, r1, c1, c0, 0   @ HSCTLR
-
-       /*
-        * Install stub vectors, using ardb's VA->PA trick.
-        */
-0:     adr     r0, 0b                                  @ PA(0)
-       movw    r1, #:lower16:__hyp_stub_vectors - 0b   @ VA(stub) - VA(0)
-       movt    r1, #:upper16:__hyp_stub_vectors - 0b
-       add     r1, r1, r0                              @ PA(stub)
-       mcr     p15, 4, r1, c12, c0, 0  @ HVBAR
-       b       exit
-
-1:     ldr     r0, =HVC_STUB_ERR
-       eret
-
-exit:
-       mov     r0, #0
-       eret
-ENDPROC(__kvm_handle_stub_hvc)
-
-       .ltorg
-
-       .globl __kvm_hyp_init_end
-__kvm_hyp_init_end:
-
-       .popsection
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
deleted file mode 100644 (file)
index 064f4f1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-
-#include <linux/linkage.h>
-
-       .text
-
-/********************************************************************
- *  Call function in Hyp mode
- *
- *
- * unsigned long kvm_call_hyp(void *hypfn, ...);
- *
- * This is not really a variadic function in the classic C-way and care must
- * be taken when calling this to ensure parameters are passed in registers
- * only, since the stack will change between the caller and the callee.
- *
- * Call the function with the first argument containing a pointer to the
- * function you wish to call in Hyp mode, and subsequent arguments will be
- * passed as r0, r1, and r2 (a maximum of 3 arguments in addition to the
- * function pointer can be passed).  The function being called must be mapped
- * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
- * passed in r0 (strictly 32bit).
- *
- * The calling convention follows the standard AAPCS:
- *   r0 - r3: caller save
- *   r12:     caller save
- *   rest:    callee save
- */
-ENTRY(__kvm_call_hyp)
-       hvc     #0
-       bx      lr
-ENDPROC(__kvm_call_hyp)
diff --git a/arch/arm/kvm/irq.h b/arch/arm/kvm/irq.h
deleted file mode 100644 (file)
index 0d257de..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * irq.h: in kernel interrupt controller related definitions
- * Copyright (c) 2016 Red Hat, Inc.
- *
- * This header is included by irqchip.c. However, on ARM, interrupt
- * controller declarations are located in include/kvm/arm_vgic.h since
- * they are mostly shared between arm and arm64.
- */
-
-#ifndef __IRQ_H
-#define __IRQ_H
-
-#include <kvm/arm_vgic.h>
-
-#endif
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
deleted file mode 100644 (file)
index eb4174f..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 - Virtual Open Systems and Columbia University
- * Author: Christoffer Dall <c.dall@virtualopensystems.com>
- */
-#include <linux/compiler.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kvm_host.h>
-#include <linux/kvm.h>
-
-#include <asm/unified.h>
-#include <asm/ptrace.h>
-#include <asm/cputype.h>
-#include <asm/kvm_arm.h>
-#include <asm/kvm_coproc.h>
-#include <asm/kvm_emulate.h>
-
-#include <kvm/arm_arch_timer.h>
-
-/******************************************************************************
- * Cortex-A15 and Cortex-A7 Reset Values
- */
-
-static struct kvm_regs cortexa_regs_reset = {
-       .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
-};
-
-
-/*******************************************************************************
- * Exported reset function
- */
-
-/**
- * kvm_reset_vcpu - sets core registers and cp15 registers to reset value
- * @vcpu: The VCPU pointer
- *
- * This function finds the right table above and sets the registers on the
- * virtual CPU struct to their architecturally defined reset values.
- */
-int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
-{
-       struct kvm_regs *reset_regs;
-
-       switch (vcpu->arch.target) {
-       case KVM_ARM_TARGET_CORTEX_A7:
-       case KVM_ARM_TARGET_CORTEX_A15:
-               reset_regs = &cortexa_regs_reset;
-               vcpu->arch.midr = read_cpuid_id();
-               break;
-       default:
-               return -ENODEV;
-       }
-
-       /* Reset core registers */
-       memcpy(&vcpu->arch.ctxt.gp_regs, reset_regs, sizeof(vcpu->arch.ctxt.gp_regs));
-
-       /* Reset CP15 registers */
-       kvm_reset_coprocs(vcpu);
-
-       /*
-        * Additional reset state handling that PSCI may have imposed on us.
-        * Must be done after all the sys_reg reset.
-        */
-       if (READ_ONCE(vcpu->arch.reset_state.reset)) {
-               unsigned long target_pc = vcpu->arch.reset_state.pc;
-
-               /* Gracefully handle Thumb2 entry point */
-               if (target_pc & 1) {
-                       target_pc &= ~1UL;
-                       vcpu_set_thumb(vcpu);
-               }
-
-               /* Propagate caller endianness */
-               if (vcpu->arch.reset_state.be)
-                       kvm_vcpu_set_be(vcpu);
-
-               *vcpu_pc(vcpu) = target_pc;
-               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
-
-               vcpu->arch.reset_state.reset = false;
-       }
-
-       /* Reset arch_timer context */
-       return kvm_timer_vcpu_reset(vcpu);
-}
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
deleted file mode 100644 (file)
index 69a9d62..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#if !defined(_TRACE_ARM_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_ARM_KVM_H
-
-#include <linux/tracepoint.h>
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kvm
-
-/* Architecturally implementation defined CP15 register access */
-TRACE_EVENT(kvm_emulate_cp15_imp,
-       TP_PROTO(unsigned long Op1, unsigned long Rt1, unsigned long CRn,
-                unsigned long CRm, unsigned long Op2, bool is_write),
-       TP_ARGS(Op1, Rt1, CRn, CRm, Op2, is_write),
-
-       TP_STRUCT__entry(
-               __field(        unsigned int,   Op1             )
-               __field(        unsigned int,   Rt1             )
-               __field(        unsigned int,   CRn             )
-               __field(        unsigned int,   CRm             )
-               __field(        unsigned int,   Op2             )
-               __field(        bool,           is_write        )
-       ),
-
-       TP_fast_assign(
-               __entry->is_write               = is_write;
-               __entry->Op1                    = Op1;
-               __entry->Rt1                    = Rt1;
-               __entry->CRn                    = CRn;
-               __entry->CRm                    = CRm;
-               __entry->Op2                    = Op2;
-       ),
-
-       TP_printk("Implementation defined CP15: %s\tp15, %u, r%u, c%u, c%u, %u",
-                       (__entry->is_write) ? "mcr" : "mrc",
-                       __entry->Op1, __entry->Rt1, __entry->CRn,
-                       __entry->CRm, __entry->Op2)
-);
-
-TRACE_EVENT(kvm_wfx,
-       TP_PROTO(unsigned long vcpu_pc, bool is_wfe),
-       TP_ARGS(vcpu_pc, is_wfe),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_pc         )
-               __field(                 bool,  is_wfe          )
-       ),
-
-       TP_fast_assign(
-               __entry->vcpu_pc                = vcpu_pc;
-               __entry->is_wfe                 = is_wfe;
-       ),
-
-       TP_printk("guest executed wf%c at: 0x%08lx",
-               __entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc)
-);
-
-TRACE_EVENT(kvm_hvc,
-       TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
-       TP_ARGS(vcpu_pc, r0, imm),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_pc         )
-               __field(        unsigned long,  r0              )
-               __field(        unsigned long,  imm             )
-       ),
-
-       TP_fast_assign(
-               __entry->vcpu_pc                = vcpu_pc;
-               __entry->r0             = r0;
-               __entry->imm            = imm;
-       ),
-
-       TP_printk("HVC at 0x%08lx (r0: 0x%08lx, imm: 0x%lx",
-                 __entry->vcpu_pc, __entry->r0, __entry->imm)
-);
-
-#endif /* _TRACE_ARM_KVM_H */
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE trace
-
-/* This part must be outside protection */
-#include <trace/define_trace.h>
diff --git a/arch/arm/kvm/vgic-v3-coproc.c b/arch/arm/kvm/vgic-v3-coproc.c
deleted file mode 100644 (file)
index ed3b2e4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * VGIC system registers handling functions for AArch32 mode
- */
-
-#include <linux/kvm.h>
-#include <linux/kvm_host.h>
-#include <asm/kvm_emulate.h>
-#include "vgic.h"
-
-int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
-                                u64 *reg)
-{
-       /*
-        * TODO: Implement for AArch32
-        */
-       return -ENXIO;
-}
-
-int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
-                               u64 *reg)
-{
-       /*
-        * TODO: Implement for AArch32
-        */
-       return -ENXIO;
-}
index cbbe03e96de8869979f64b0fe1ae1347b35dea1c..76838255b5fa56ec24cf121bab05dee7b2883627 100644 (file)
@@ -21,7 +21,7 @@ menuconfig ARCH_EXYNOS
        select EXYNOS_SROM
        select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
        select GPIOLIB
-       select HAVE_ARM_ARCH_TIMER if ARCH_EXYNOS5 && VIRTUALIZATION
+       select HAVE_ARM_ARCH_TIMER if ARCH_EXYNOS5
        select HAVE_ARM_SCU if SMP
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
index 5d0d0f86e790b5a39110a6aeb8ad66c5f9485933..69a337df619f185806d02627900663ce4a54a98c 100644 (file)
@@ -63,9 +63,6 @@ static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
 static unsigned int ecc_mask __initdata = 0;
 pgprot_t pgprot_user;
 pgprot_t pgprot_kernel;
-pgprot_t pgprot_hyp_device;
-pgprot_t pgprot_s2;
-pgprot_t pgprot_s2_device;
 
 EXPORT_SYMBOL(pgprot_user);
 EXPORT_SYMBOL(pgprot_kernel);
@@ -75,15 +72,8 @@ struct cachepolicy {
        unsigned int    cr_mask;
        pmdval_t        pmd;
        pteval_t        pte;
-       pteval_t        pte_s2;
 };
 
-#ifdef CONFIG_ARM_LPAE
-#define s2_policy(policy)      policy
-#else
-#define s2_policy(policy)      0
-#endif
-
 unsigned long kimage_voffset __ro_after_init;
 
 static struct cachepolicy cache_policies[] __initdata = {
@@ -92,31 +82,26 @@ static struct cachepolicy cache_policies[] __initdata = {
                .cr_mask        = CR_W|CR_C,
                .pmd            = PMD_SECT_UNCACHED,
                .pte            = L_PTE_MT_UNCACHED,
-               .pte_s2         = s2_policy(L_PTE_S2_MT_UNCACHED),
        }, {
                .policy         = "buffered",
                .cr_mask        = CR_C,
                .pmd            = PMD_SECT_BUFFERED,
                .pte            = L_PTE_MT_BUFFERABLE,
-               .pte_s2         = s2_policy(L_PTE_S2_MT_UNCACHED),
        }, {
                .policy         = "writethrough",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WT,
                .pte            = L_PTE_MT_WRITETHROUGH,
-               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITETHROUGH),
        }, {
                .policy         = "writeback",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WB,
                .pte            = L_PTE_MT_WRITEBACK,
-               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITEBACK),
        }, {
                .policy         = "writealloc",
                .cr_mask        = 0,
                .pmd            = PMD_SECT_WBWA,
                .pte            = L_PTE_MT_WRITEALLOC,
-               .pte_s2         = s2_policy(L_PTE_S2_MT_WRITEBACK),
        }
 };
 
@@ -246,9 +231,6 @@ static struct mem_type mem_types[] __ro_after_init = {
        [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
                                  L_PTE_SHARED,
-               .prot_pte_s2    = s2_policy(PROT_PTE_S2_DEVICE) |
-                                 s2_policy(L_PTE_S2_MT_DEV_SHARED) |
-                                 L_PTE_SHARED,
                .prot_l1        = PMD_TYPE_TABLE,
                .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_S,
                .domain         = DOMAIN_IO,
@@ -434,7 +416,6 @@ static void __init build_mem_type_table(void)
        struct cachepolicy *cp;
        unsigned int cr = get_cr();
        pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
-       pteval_t hyp_device_pgprot, s2_pgprot, s2_device_pgprot;
        int cpu_arch = cpu_architecture();
        int i;
 
@@ -558,9 +539,6 @@ static void __init build_mem_type_table(void)
         */
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
-       s2_pgprot = cp->pte_s2;
-       hyp_device_pgprot = mem_types[MT_DEVICE].prot_pte;
-       s2_device_pgprot = mem_types[MT_DEVICE].prot_pte_s2;
 
 #ifndef CONFIG_ARM_LPAE
        /*
@@ -604,7 +582,6 @@ static void __init build_mem_type_table(void)
                        user_pgprot |= L_PTE_SHARED;
                        kern_pgprot |= L_PTE_SHARED;
                        vecs_pgprot |= L_PTE_SHARED;
-                       s2_pgprot |= L_PTE_SHARED;
                        mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
                        mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
                        mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
@@ -666,9 +643,6 @@ static void __init build_mem_type_table(void)
        pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
        pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
                                 L_PTE_DIRTY | kern_pgprot);
-       pgprot_s2  = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | s2_pgprot);
-       pgprot_s2_device  = __pgprot(s2_device_pgprot);
-       pgprot_hyp_device  = __pgprot(hyp_device_pgprot);
 
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
index 25fec4bde43af6f66bbb0e170a888d154eb82535..a358e97572c14c58d55d732926cf3f211a71a410 100644 (file)
@@ -32,7 +32,7 @@ static inline void gic_write_eoir(u32 irq)
        isb();
 }
 
-static inline void gic_write_dir(u32 irq)
+static __always_inline void gic_write_dir(u32 irq)
 {
        write_sysreg_s(irq, SYS_ICC_DIR_EL1);
        isb();
index 806e9dc2a852a43d54f9eeb89122684553971b16..a4d1b5f771f6baebd64c3c291be937e84eddd397 100644 (file)
@@ -69,7 +69,7 @@ static inline int icache_is_aliasing(void)
        return test_bit(ICACHEF_ALIASING, &__icache_flags);
 }
 
-static inline int icache_is_vpipt(void)
+static __always_inline int icache_is_vpipt(void)
 {
        return test_bit(ICACHEF_VPIPT, &__icache_flags);
 }
index 665c78e0665a65ea89f40442bef31b55bebf9147..e6cca3d4acf702f060bb35996ead0762566de7b6 100644 (file)
@@ -145,7 +145,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static inline void __flush_icache_all(void)
+static __always_inline void __flush_icache_all(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
                return;
index 92ef9539874a663b3bd693c4e834a5cf134a21d6..2a746b99e937f489cac93452fe4a11dfbc1c17d8 100644 (file)
@@ -435,13 +435,13 @@ cpuid_feature_extract_signed_field(u64 features, int field)
        return cpuid_feature_extract_signed_field_width(features, field, 4);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
 {
        return (u64)(features << (64 - width - field)) >> (64 - width);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field(u64 features, int field)
 {
        return cpuid_feature_extract_unsigned_field_width(features, field, 4);
@@ -564,7 +564,7 @@ static inline bool system_supports_mixed_endian(void)
        return val == 0x1;
 }
 
-static inline bool system_supports_fpsimd(void)
+static __always_inline bool system_supports_fpsimd(void)
 {
        return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
 }
@@ -575,13 +575,13 @@ static inline bool system_uses_ttbr0_pan(void)
                !cpus_have_const_cap(ARM64_HAS_PAN);
 }
 
-static inline bool system_supports_sve(void)
+static __always_inline bool system_supports_sve(void)
 {
        return IS_ENABLED(CONFIG_ARM64_SVE) &&
                cpus_have_const_cap(ARM64_SVE);
 }
 
-static inline bool system_supports_cnp(void)
+static __always_inline bool system_supports_cnp(void)
 {
        return IS_ENABLED(CONFIG_ARM64_CNP) &&
                cpus_have_const_cap(ARM64_HAS_CNP);
index 4e531f57147d122aec8c87a800a08e33400b3c51..6facd1308e7c28c54ef35e762652f7cdb364322e 100644 (file)
@@ -34,7 +34,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 }
 
 #define __raw_writel __raw_writel
-static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
        asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
 }
@@ -69,7 +69,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 }
 
 #define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
+static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        u32 val;
        asm volatile(ALTERNATIVE("ldr %w0, [%1]",
index 688c63412cc27922aa2b5faba8d8fc808bef674b..a30b4eec7cb40048c92d9d4261765446c2365af8 100644 (file)
@@ -36,7 +36,7 @@ void kvm_inject_undef32(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 
-static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
 {
        return !(vcpu->arch.hcr_el2 & HCR_RW);
 }
@@ -89,7 +89,8 @@ static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
 static inline void vcpu_clear_wfx_traps(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.hcr_el2 &= ~HCR_TWE;
-       if (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count))
+       if (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) ||
+           vcpu->kvm->arch.vgic.nassgireq)
                vcpu->arch.hcr_el2 &= ~HCR_TWI;
        else
                vcpu->arch.hcr_el2 |= HCR_TWI;
@@ -127,7 +128,7 @@ static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
        vcpu->arch.vsesr_el2 = vsesr;
 }
 
-static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
 }
@@ -153,17 +154,17 @@ static inline void vcpu_write_elr_el1(const struct kvm_vcpu *vcpu, unsigned long
                *__vcpu_elr_el1(vcpu) = v;
 }
 
-static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate;
 }
 
-static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
 }
 
-static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
 {
        if (vcpu_mode_is_32bit(vcpu))
                return kvm_condition_valid32(vcpu);
@@ -181,13 +182,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
  * coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
  * AArch32 with banked registers.
  */
-static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
+static __always_inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
                                         u8 reg_num)
 {
        return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
 }
 
-static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
+static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
                                unsigned long val)
 {
        if (reg_num != 31)
@@ -264,12 +265,12 @@ static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
        return mode != PSR_MODE_EL0t;
 }
 
-static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
+static __always_inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.esr_el2;
 }
 
-static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
 
@@ -279,12 +280,12 @@ static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
        return -1;
 }
 
-static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.far_el2;
 }
 
-static inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
+static __always_inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
 {
        return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8;
 }
@@ -299,7 +300,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK;
 }
 
-static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
 }
@@ -319,17 +320,17 @@ static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF);
 }
 
-static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
        return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
 }
 
-static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
+static __always_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)
+static __always_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 */
@@ -340,18 +341,18 @@ static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
 }
 
-static inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
 {
        return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT);
 }
 
 /* This one is not specific to Data Abort */
-static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL);
 }
 
-static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 {
        return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
 }
@@ -361,17 +362,17 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
-static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
 {
        switch (kvm_vcpu_trap_get_fault(vcpu)) {
        case FSC_SEA:
@@ -390,7 +391,7 @@ static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
        }
 }
 
-static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
        return ESR_ELx_SYS64_ISS_RT(esr);
@@ -504,7 +505,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
        return data;            /* Leave LE untouched */
 }
 
-static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
+static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
 {
        if (vcpu_mode_is_32bit(vcpu))
                kvm_skip_instr32(vcpu, is_wide_instr);
@@ -519,7 +520,7 @@ static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
  * Skip an instruction which has been emulated at hyp while most guest sysregs
  * are live.
  */
-static inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
+static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
 {
        *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
        vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);
index d87aa609d2b6f3e49a5b44ccd523b89753289846..32c8a675e5a4a33c89a12cdfd69d3d558b92f95f 100644 (file)
@@ -44,6 +44,7 @@
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
 #define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
+#define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -626,38 +627,6 @@ static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
 static inline void kvm_clr_pmu_events(u32 clr) {}
 #endif
 
-static inline void kvm_arm_vhe_guest_enter(void)
-{
-       local_daif_mask();
-
-       /*
-        * Having IRQs masked via PMR when entering the guest means the GIC
-        * will not signal the CPU of interrupts of lower priority, and the
-        * only way to get out will be via guest exceptions.
-        * Naturally, we want to avoid this.
-        *
-        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
-        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
-        */
-       pmr_sync();
-}
-
-static inline void kvm_arm_vhe_guest_exit(void)
-{
-       /*
-        * local_daif_restore() takes care to properly restore PSTATE.DAIF
-        * and the GIC PMR if the host is using IRQ priorities.
-        */
-       local_daif_restore(DAIF_PROCCTX_NOIRQ);
-
-       /*
-        * When we exit from the guest we change a number of CPU configuration
-        * parameters, such as traps.  Make sure these changes take effect
-        * before running the host or additional guests.
-        */
-       isb();
-}
-
 #define KVM_BP_HARDEN_UNKNOWN          -1
 #define KVM_BP_HARDEN_WA_NEEDED                0
 #define KVM_BP_HARDEN_NOT_REQUIRED     1
index a3a6a2ba9a635efd7feec4542f4c0b281052521c..fe57f60f06a8944fff74b2e3f1ed5de6d1790626 100644 (file)
 #define read_sysreg_el2(r)     read_sysreg_elx(r, _EL2, _EL1)
 #define write_sysreg_el2(v,r)  write_sysreg_elx(v, r, _EL2, _EL1)
 
+/*
+ * Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
+ * static inline can allow the compiler to out-of-line this. KVM always wants
+ * the macro version as its always inlined.
+ */
+#define __kvm_swab32(x)        ___constant_swab32(x)
+
 int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
index 53d846f1bfe70497b81d2457c9a6eefe543fc61f..785762860c63fd5c435f575cffdf22f2c69d8b27 100644 (file)
@@ -93,7 +93,7 @@ void kvm_update_va_mask(struct alt_instr *alt,
                        __le32 *origptr, __le32 *updptr, int nr_inst);
 void kvm_compute_layout(void);
 
-static inline unsigned long __kern_hyp_va(unsigned long v)
+static __always_inline unsigned long __kern_hyp_va(unsigned long v)
 {
        asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
                                    "ror %0, %0, #1\n"
@@ -473,6 +473,7 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
 extern void *__kvm_bp_vect_base;
 extern int __kvm_harden_el2_vector_slot;
 
+/*  This is only called on a VHE system */
 static inline void *kvm_get_hyp_vector(void)
 {
        struct bp_hardening_data *data = arm64_get_bp_hardening_data();
index d429f7701c3670101b62540f79c65ec711cba4d1..5d10051c3e62e839808d9ee0a56e0274d934589a 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 
-#define __LSE_PREAMBLE ".arch armv8-a+lse\n"
+#define __LSE_PREAMBLE ".arch_extension lse\n"
 
 #include <linux/compiler_types.h>
 #include <linux/export.h>
index a4f9ca5479b063a012ec400c5ee623594d44e693..4d94676e5a8b6b08e0043b09bf7728ec1eb15642 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned long kaslr_offset(void)
        ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
 
 #define untagged_addr(addr)    ({                                      \
-       u64 __addr = (__force u64)addr;                                 \
+       u64 __addr = (__force u64)(addr);                                       \
        __addr &= __untagged_addr(__addr);                              \
        (__force __typeof__(addr))__addr;                               \
 })
index 0958ed6191aa344dcc84c965cc1f1e410a53540f..61fd26752adcb3bf19f55a7d6e3f03b8581f686e 100644 (file)
@@ -83,7 +83,7 @@ static inline bool is_kernel_in_hyp_mode(void)
        return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
-static inline bool has_vhe(void)
+static __always_inline bool has_vhe(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
                return true;
index f3e0ab9615659ea7570a79e1fd6dada85821fe3b..600010cd6d1d268208b3d41d6b36a469c04ed6b6 100644 (file)
@@ -624,7 +624,7 @@ static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
 }
 
 /* Switch to the guest for VHE systems running in EL2 */
-int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpu_context *host_ctxt;
        struct kvm_cpu_context *guest_ctxt;
@@ -677,7 +677,42 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
-NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
+NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe);
+
+int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+{
+       int ret;
+
+       local_daif_mask();
+
+       /*
+        * Having IRQs masked via PMR when entering the guest means the GIC
+        * will not signal the CPU of interrupts of lower priority, and the
+        * only way to get out will be via guest exceptions.
+        * Naturally, we want to avoid this.
+        *
+        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
+        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
+        */
+       pmr_sync();
+
+       ret = __kvm_vcpu_run_vhe(vcpu);
+
+       /*
+        * local_daif_restore() takes care to properly restore PSTATE.DAIF
+        * and the GIC PMR if the host is using IRQ priorities.
+        */
+       local_daif_restore(DAIF_PROCCTX_NOIRQ);
+
+       /*
+        * When we exit from the guest we change a number of CPU configuration
+        * parameters, such as traps.  Make sure these changes take effect
+        * before running the host or additional guests.
+        */
+       isb();
+
+       return ret;
+}
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
index 29ee1feba4eb7de12d55d8c8a99f64e2577e73e5..4f3a087e36d51c6e53d2fedc9370b1edcdbca0c9 100644 (file)
@@ -69,14 +69,14 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
                u32 data = vcpu_get_reg(vcpu, rd);
                if (__is_be(vcpu)) {
                        /* guest pre-swabbed data, undo this for writel() */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                writel_relaxed(data, addr);
        } else {
                u32 data = readl_relaxed(addr);
                if (__is_be(vcpu)) {
                        /* guest expects swabbed data */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                vcpu_set_reg(vcpu, rd, data);
        }
index da09c884cc305f20ba912c3b1ecd3b9ea54f8bbc..047427f71d835a6022023c7d69e7a42864d9caac 100644 (file)
@@ -9,7 +9,6 @@ config CSKY
        select ARCH_USE_QUEUED_RWLOCKS if NR_CPUS>2
        select COMMON_CLK
        select CLKSRC_MMIO
-       select CLKSRC_OF
        select CSKY_MPINTC if CPU_CK860
        select CSKY_MP_TIMER if CPU_CK860
        select CSKY_APB_INTC
@@ -37,6 +36,7 @@ config CSKY
        select GX6605S_TIMER if CPU_CK610
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_AUDITSYSCALL
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
@@ -47,8 +47,8 @@ config CSKY
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_DMA_API_DEBUG
        select HAVE_DMA_CONTIGUOUS
+       select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
        select MAY_HAVE_SPARSE_IRQ
        select MODULES_USE_ELF_RELA if MODULES
@@ -59,6 +59,11 @@ config CSKY
        select TIMER_OF
        select USB_ARCH_HAS_EHCI
        select USB_ARCH_HAS_OHCI
+       select GENERIC_PCI_IOMAP
+       select HAVE_PCI
+       select PCI_DOMAINS_GENERIC if PCI
+       select PCI_SYSCALL if PCI
+       select PCI_MSI if PCI
 
 config CPU_HAS_CACHEV2
        bool
@@ -75,7 +80,7 @@ config CPU_HAS_TLBI
 config CPU_HAS_LDSTEX
        bool
        help
-         For SMP, CPU needs "ldex&stex" instrcutions to atomic operations.
+         For SMP, CPU needs "ldex&stex" instructions for atomic operations.
 
 config CPU_NEED_TLBSYNC
        bool
@@ -188,6 +193,40 @@ config CPU_PM_STOP
        bool "stop"
 endchoice
 
+menuconfig HAVE_TCM
+       bool "Tightly-Coupled/Sram Memory"
+       select GENERIC_ALLOCATOR
+       help
+         The implementation are not only used by TCM (Tightly-Coupled Meory)
+         but also used by sram on SOC bus. It follow existed linux tcm
+         software interface, so that old tcm application codes could be
+         re-used directly.
+
+if HAVE_TCM
+config ITCM_RAM_BASE
+       hex "ITCM ram base"
+       default 0xffffffff
+
+config ITCM_NR_PAGES
+       int "Page count of ITCM size: NR*4KB"
+       range 1 256
+       default 32
+
+config HAVE_DTCM
+       bool "DTCM Support"
+
+config DTCM_RAM_BASE
+       hex "DTCM ram base"
+       depends on HAVE_DTCM
+       default 0xffffffff
+
+config DTCM_NR_PAGES
+       int "Page count of DTCM size: NR*4KB"
+       depends on HAVE_DTCM
+       range 1 256
+       default 32
+endif
+
 config CPU_HAS_VDSP
        bool "CPU has VDSP coprocessor"
        depends on CPU_HAS_FPU && CPU_HAS_FPUV2
@@ -196,6 +235,10 @@ config CPU_HAS_FPU
        bool "CPU has FPU coprocessor"
        depends on CPU_CK807 || CPU_CK810 || CPU_CK860
 
+config CPU_HAS_ICACHE_INS
+       bool "CPU has Icache invalidate instructions"
+       depends on CPU_HAS_CACHEV2
+
 config CPU_HAS_TEE
        bool "CPU has Trusted Execution Environment"
        depends on CPU_CK810
@@ -235,4 +278,6 @@ config HOTPLUG_CPU
          Say N if you want to disable CPU hotplug.
 endmenu
 
+source "arch/csky/Kconfig.platforms"
+
 source "kernel/Kconfig.hz"
diff --git a/arch/csky/Kconfig.platforms b/arch/csky/Kconfig.platforms
new file mode 100644 (file)
index 0000000..639e17f
--- /dev/null
@@ -0,0 +1,9 @@
+menu "Platform drivers selection"
+
+config ARCH_CSKY_DW_APB_ICTL
+       bool "Select dw-apb interrupt controller"
+       select DW_APB_ICTL
+       default y
+       help
+         This enables support for snps dw-apb-ictl
+endmenu
index 79ef9e8c1afddc1a520fb56cd2817be38e4cae4c..d3e04208d53c23e36eee552e89e484ef81d8f2c5 100644 (file)
@@ -48,9 +48,8 @@ extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, u
 
 #define flush_icache_page(vma, page)           do {} while (0);
 #define flush_icache_range(start, end)         cache_wbinv_range(start, end)
-
-#define flush_icache_user_range(vma,page,addr,len) \
-       flush_dcache_page(page)
+#define flush_icache_mm_range(mm, start, end)  cache_wbinv_range(start, end)
+#define flush_icache_deferred(mm)              do {} while (0);
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 do { \
index 7ab78bd0f3b13f7e52be13445314ef956566fa73..f35a9f3315ee6f62b126eb54b46f72a90d22da41 100644 (file)
 #define LSAVE_A4       40
 #define LSAVE_A5       44
 
+#define usp ss1
+
 .macro USPTOKSP
-       mtcr    sp, ss1
+       mtcr    sp, usp
        mfcr    sp, ss0
 .endm
 
 .macro KSPTOUSP
        mtcr    sp, ss0
-       mfcr    sp, ss1
+       mfcr    sp, usp
 .endm
 
 .macro SAVE_ALL epc_inc
        add     lr, r13
        stw     lr, (sp, 8)
 
+       mov     lr, sp
+       addi    lr, 32
+       addi    lr, 32
+       addi    lr, 16
+       bt      2f
        mfcr    lr, ss1
+2:
        stw     lr, (sp, 16)
 
        stw     a0, (sp, 20)
        ldw     a0, (sp, 12)
        mtcr    a0, epsr
        btsti   a0, 31
+       bt      1f
        ldw     a0, (sp, 16)
        mtcr    a0, ss1
-
+1:
        ldw     a0, (sp, 24)
        ldw     a1, (sp, 28)
        ldw     a2, (sp, 32)
        addi    sp, 32
        addi    sp, 8
 
-       bt      1f
+       bt      2f
        KSPTOUSP
-1:
+2:
        rte
 .endm
 
index 5bb887b275e1213e4e6e9e77b894a7ef490d06c7..790f1ebfba44ba925ccd94f1927b61e03137dbc6 100644 (file)
@@ -6,46 +6,80 @@
 #include <linux/mm.h>
 #include <asm/cache.h>
 
-void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+                     pte_t *pte)
 {
-       unsigned long start;
+       unsigned long addr;
+       struct page *page;
 
-       start = (unsigned long) kmap_atomic(page);
+       page = pfn_to_page(pte_pfn(*pte));
+       if (page == ZERO_PAGE(0))
+               return;
 
-       cache_wbinv_range(start, start + PAGE_SIZE);
+       if (test_and_set_bit(PG_dcache_clean, &page->flags))
+               return;
 
-       kunmap_atomic((void *)start);
-}
+       addr = (unsigned long) kmap_atomic(page);
 
-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-                            unsigned long vaddr, int len)
-{
-       unsigned long kaddr;
+       dcache_wb_range(addr, addr + PAGE_SIZE);
 
-       kaddr = (unsigned long) kmap_atomic(page) + (vaddr & ~PAGE_MASK);
+       if (vma->vm_flags & VM_EXEC)
+               icache_inv_range(addr, addr + PAGE_SIZE);
+
+       kunmap_atomic((void *) addr);
+}
 
-       cache_wbinv_range(kaddr, kaddr + len);
+void flush_icache_deferred(struct mm_struct *mm)
+{
+       unsigned int cpu = smp_processor_id();
+       cpumask_t *mask = &mm->context.icache_stale_mask;
 
-       kunmap_atomic((void *)kaddr);
+       if (cpumask_test_cpu(cpu, mask)) {
+               cpumask_clear_cpu(cpu, mask);
+               /*
+                * Ensure the remote hart's writes are visible to this hart.
+                * This pairs with a barrier in flush_icache_mm.
+                */
+               smp_mb();
+               local_icache_inv_all(NULL);
+       }
 }
 
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
-                     pte_t *pte)
+void flush_icache_mm_range(struct mm_struct *mm,
+               unsigned long start, unsigned long end)
 {
-       unsigned long addr, pfn;
-       struct page *page;
+       unsigned int cpu;
+       cpumask_t others, *mask;
 
-       pfn = pte_pfn(*pte);
-       if (unlikely(!pfn_valid(pfn)))
-               return;
+       preempt_disable();
 
-       page = pfn_to_page(pfn);
-       if (page == ZERO_PAGE(0))
+#ifdef CONFIG_CPU_HAS_ICACHE_INS
+       if (mm == current->mm) {
+               icache_inv_range(start, end);
+               preempt_enable();
                return;
+       }
+#endif
 
-       addr = (unsigned long) kmap_atomic(page);
+       /* Mark every hart's icache as needing a flush for this MM. */
+       mask = &mm->context.icache_stale_mask;
+       cpumask_setall(mask);
 
-       cache_wbinv_range(addr, addr + PAGE_SIZE);
+       /* Flush this hart's I$ now, and mark it as flushed. */
+       cpu = smp_processor_id();
+       cpumask_clear_cpu(cpu, mask);
+       local_icache_inv_all(NULL);
 
-       kunmap_atomic((void *) addr);
+       /*
+        * Flush the I$ of other harts concurrently executing, and mark them as
+        * flushed.
+        */
+       cpumask_andnot(&others, mm_cpumask(mm), cpumask_of(cpu));
+
+       if (mm != current->active_mm || !cpumask_empty(&others)) {
+               on_each_cpu_mask(&others, local_icache_inv_all, NULL, 1);
+               cpumask_clear(mask);
+       }
+
+       preempt_enable();
 }
index b8db5e0b2fe3c6448907398cba030c7d9abb9223..a565e00c3f70b2e51420cf61650c59cf68c199dc 100644 (file)
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
 #define flush_cache_dup_mm(mm)                 do { } while (0)
+#define flush_cache_range(vma, start, end)     do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 
-#define flush_cache_range(vma, start, end) \
-       do { \
-               if (vma->vm_flags & VM_EXEC) \
-                       icache_inv_all(); \
-       } while (0)
+#define PG_dcache_clean                PG_arch_1
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+static inline void flush_dcache_page(struct page *page)
+{
+       if (test_bit(PG_dcache_clean, &page->flags))
+               clear_bit(PG_dcache_clean, &page->flags);
+}
 
-#define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)                        do { } while (0)
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_icache_page(vma, page)           do { } while (0)
 
 #define flush_icache_range(start, end)         cache_wbinv_range(start, end)
 
-void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
-                            unsigned long vaddr, int len);
+void flush_icache_mm_range(struct mm_struct *mm,
+                       unsigned long start, unsigned long end);
+void flush_icache_deferred(struct mm_struct *mm);
 
 #define flush_cache_vmap(start, end)           do { } while (0)
 #define flush_cache_vunmap(start, end)         do { } while (0)
@@ -38,7 +41,13 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { \
        memcpy(dst, src, len); \
-       cache_wbinv_range((unsigned long)dst, (unsigned long)dst + len); \
+       if (vma->vm_flags & VM_EXEC) { \
+               dcache_wb_range((unsigned long)dst, \
+                               (unsigned long)dst + len); \
+               flush_icache_mm_range(current->mm, \
+                               (unsigned long)dst, \
+                               (unsigned long)dst + len); \
+               } \
 } while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
        memcpy(dst, src, len)
index 9897a16b45e5dcc75b4e6638a8ecd1153be661e9..94a7a58765dffe6a0b28bb1acb36bf6c380fbbb6 100644 (file)
 
        mfcr    lr, epsr
        stw     lr, (sp, 12)
+       btsti   lr, 31
+       bf      1f
+       addi    lr, sp, 152
+       br      2f
+1:
        mfcr    lr, usp
+2:
        stw     lr, (sp, 16)
 
        stw     a0, (sp, 20)
        mtcr    a0, epc
        ldw     a0, (sp, 12)
        mtcr    a0, epsr
+       btsti   a0, 31
        ldw     a0, (sp, 16)
        mtcr    a0, usp
+       mtcr    a0, ss0
 
 #ifdef CONFIG_CPU_HAS_HILO
        ldw     a0, (sp, 140)
@@ -86,6 +94,9 @@
        addi    sp, 40
        ldm     r16-r30, (sp)
        addi    sp, 72
+       bf      1f
+       mfcr    sp, ss0
+1:
        rte
 .endm
 
index 7ef42895dfb03b294c77b0f9687054cfe9d94571..af722e4dfb47d8239c969b25834e9b231a9b4244 100644 (file)
@@ -10,9 +10,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_DEFAULT_DEADLINE=y
-CONFIG_CPU_CK807=y
-CONFIG_CPU_HAS_FPU=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -27,10 +24,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_TTY_PRINTK=y
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_CSKY_MPTIMER=y
-CONFIG_GX6605S_TIMER=y
 CONFIG_PM_DEVFREQ=y
 CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
 CONFIG_DEVFREQ_GOV_PERFORMANCE=y
@@ -56,6 +50,4 @@ CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
index bc15a26c782f9268fc47d1617594881d8d9bec29..4130e3eaa766711685f776b8b22cb234edce5379 100644 (file)
@@ -28,7 +28,6 @@ generic-y += local64.h
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
 generic-y += module.h
-generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += qrwlock.h
index 1d5fc2f78fd7e8c634b87e61eb9219fbc4f67ba3..4b5c09bf1d25e3a9b9720bd58f99effcdab09610 100644 (file)
@@ -16,6 +16,7 @@ void dcache_wb_line(unsigned long start);
 
 void icache_inv_range(unsigned long start, unsigned long end);
 void icache_inv_all(void);
+void local_icache_inv_all(void *priv);
 
 void dcache_wb_range(unsigned long start, unsigned long end);
 void dcache_wbinv_all(void);
index a96da67261ae51fd67f48291489ef709874ac148..f0b8f25429a27f723c191888f624b53c0d778529 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef __ASM_CSKY_CACHEFLUSH_H
 #define __ASM_CSKY_CACHEFLUSH_H
 
+#include <linux/mm.h>
 #include <abi/cacheflush.h>
 
 #endif /* __ASM_CSKY_CACHEFLUSH_H */
index 380ff0a307df02095f1585d021984a7167007b2b..81f9477d5330c95e2c964294fb782a5aea3aeaf0 100644 (file)
@@ -5,12 +5,16 @@
 #define __ASM_CSKY_FIXMAP_H
 
 #include <asm/page.h>
+#include <asm/memory.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
 #endif
 
 enum fixed_addresses {
+#ifdef CONFIG_HAVE_TCM
+       FIX_TCM = TCM_NR_PAGES,
+#endif
 #ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN,
        FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
@@ -18,10 +22,13 @@ enum fixed_addresses {
        __end_of_fixed_addresses
 };
 
-#define FIXADDR_TOP    0xffffc000
 #define FIXADDR_SIZE   (__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START  (FIXADDR_TOP - FIXADDR_SIZE)
 
 #include <asm-generic/fixmap.h>
 
+extern void fixrange_init(unsigned long start, unsigned long end,
+       pgd_t *pgd_base);
+extern void __init fixaddr_init(void);
+
 #endif /* __ASM_CSKY_FIXMAP_H */
diff --git a/arch/csky/include/asm/memory.h b/arch/csky/include/asm/memory.h
new file mode 100644 (file)
index 0000000..a65c675
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_CSKY_MEMORY_H
+#define __ASM_CSKY_MEMORY_H
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+
+#define FIXADDR_TOP    _AC(0xffffc000, UL)
+#define PKMAP_BASE     _AC(0xff800000, UL)
+#define VMALLOC_START  _AC(0xc0008000, UL)
+#define VMALLOC_END    (PKMAP_BASE - (PAGE_SIZE * 2))
+
+#ifdef CONFIG_HAVE_TCM
+#ifdef CONFIG_HAVE_DTCM
+#define TCM_NR_PAGES   (CONFIG_ITCM_NR_PAGES + CONFIG_DTCM_NR_PAGES)
+#else
+#define TCM_NR_PAGES   (CONFIG_ITCM_NR_PAGES)
+#endif
+#define FIXADDR_TCM    _AC(FIXADDR_TOP - (TCM_NR_PAGES * PAGE_SIZE), UL)
+#endif
+
+#endif
index b382a14ea4ec72535393b4a6962b1f1020ab0b7e..26fbb1d15df08ea711f73efe26b39bc356312cc0 100644 (file)
@@ -7,6 +7,7 @@
 typedef struct {
        atomic64_t      asid;
        void *vdso;
+       cpumask_t       icache_stale_mask;
 } mm_context_t;
 
 #endif /* __ASM_CSKY_MMU_H */
index 0285b0ad18b6f2bce9276396461f9a1ffc2ed2f2..abdf1f1cb6ec991248ac17d7dc63881c479616ef 100644 (file)
@@ -43,5 +43,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
        write_mmu_entryhi(next->context.asid.counter);
+
+       flush_icache_deferred(next);
 }
 #endif /* __ASM_CSKY_MMU_CONTEXT_H */
diff --git a/arch/csky/include/asm/pci.h b/arch/csky/include/asm/pci.h
new file mode 100644 (file)
index 0000000..ebc765b
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_CSKY_PCI_H
+#define __ASM_CSKY_PCI_H
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#define PCIBIOS_MIN_IO         0
+#define PCIBIOS_MIN_MEM                0
+
+/* C-SKY shim does not initialize PCI bus */
+#define pcibios_assign_all_busses() 1
+
+extern int isa_dma_bridge_buggy;
+
+#ifdef CONFIG_PCI
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       /* no legacy IRQ on csky */
+       return -ENODEV;
+}
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+       /* always show the domain in /proc */
+       return 1;
+}
+#endif  /* CONFIG_PCI */
+
+#endif  /* __ASM_CSKY_PCI_H */
index 4b2a41e15f2e4231b0c1905eb3ec38628359fe33..9b7764cb76450f8d205e0996047d2866ae55d0eb 100644 (file)
@@ -5,6 +5,7 @@
 #define __ASM_CSKY_PGTABLE_H
 
 #include <asm/fixmap.h>
+#include <asm/memory.h>
 #include <asm/addrspace.h>
 #include <abi/pgtable-bits.h>
 #include <asm-generic/pgtable-nopmd.h>
 #define USER_PTRS_PER_PGD      (0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_ADDRESS     0UL
 
-#define PKMAP_BASE             (0xff800000)
-
-#define VMALLOC_START          (0xc0008000)
-#define VMALLOC_END            (PKMAP_BASE - 2*PAGE_SIZE)
-
 /*
  * C-SKY is two-level paging structure:
  */
diff --git a/arch/csky/include/asm/stackprotector.h b/arch/csky/include/asm/stackprotector.h
new file mode 100644 (file)
index 0000000..d7cd4e5
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_STACKPROTECTOR_H
+#define _ASM_STACKPROTECTOR_H 1
+
+#include <linux/random.h>
+#include <linux/version.h>
+
+extern unsigned long __stack_chk_guard;
+
+/*
+ * Initialize the stackprotector canary value.
+ *
+ * NOTE: this must only be called from functions that never return,
+ * and it must always be inlined.
+ */
+static __always_inline void boot_init_stack_canary(void)
+{
+       unsigned long canary;
+
+       /* Try to get a semi random initial value. */
+       get_random_bytes(&canary, sizeof(canary));
+       canary ^= LINUX_VERSION_CODE;
+       canary &= CANARY_MASK;
+
+       current->stack_canary = canary;
+       __stack_chk_guard = current->stack_canary;
+}
+
+#endif /* __ASM_SH_STACKPROTECTOR_H */
diff --git a/arch/csky/include/asm/tcm.h b/arch/csky/include/asm/tcm.h
new file mode 100644 (file)
index 0000000..2b135ce
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_CSKY_TCM_H
+#define __ASM_CSKY_TCM_H
+
+#ifndef CONFIG_HAVE_TCM
+#error "You should not be including tcm.h unless you have a TCM!"
+#endif
+
+#include <linux/compiler.h>
+
+/* Tag variables with this */
+#define __tcmdata __section(.tcm.data)
+/* Tag constants with this */
+#define __tcmconst __section(.tcm.rodata)
+/* Tag functions inside TCM called from outside TCM with this */
+#define __tcmfunc __section(.tcm.text) noinline
+/* Tag function inside TCM called from inside TCM  with this */
+#define __tcmlocalfunc __section(.tcm.text)
+
+void *tcm_alloc(size_t len);
+void tcm_free(void *addr, size_t len);
+
+#endif
index 211c983c7282d13f3b75150e686c8e815fd7777b..ba40189297338d1de36b9cff54d76f0746b344c6 100644 (file)
@@ -1,7 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
 #include <asm-generic/unistd.h>
index 5b84f11485aeb8c6794699c54250cf8c54f5a91d..3821ef9b75672d8a5af90839ffa7f95cfdb4da50 100644 (file)
@@ -17,10 +17,12 @@ ENTRY(csky_cmpxchg)
        mfcr    a3, epc
        addi    a3, TRAP0_SIZE
 
-       subi    sp, 8
+       subi    sp, 16
        stw     a3, (sp, 0)
        mfcr    a3, epsr
        stw     a3, (sp, 4)
+       mfcr    a3, usp
+       stw     a3, (sp, 8)
 
        psrset  ee
 #ifdef CONFIG_CPU_HAS_LDSTEX
@@ -47,7 +49,9 @@ ENTRY(csky_cmpxchg)
        mtcr    a3, epc
        ldw     a3, (sp, 4)
        mtcr    a3, epsr
-       addi    sp, 8
+       ldw     a3, (sp, 8)
+       mtcr    a3, usp
+       addi    sp, 16
        KSPTOUSP
        rte
 END(csky_cmpxchg)
index f320d9248a225fe31941129ccd2b4225c47f36d1..f7b231ca269a0dbc2b5fd76dbffcb5429fb01c6d 100644 (file)
 
 struct cpuinfo_csky cpu_data[NR_CPUS];
 
+#ifdef CONFIG_STACKPROTECTOR
+#include <linux/stackprotector.h>
+unsigned long __stack_chk_guard __read_mostly;
+EXPORT_SYMBOL(__stack_chk_guard);
+#endif
+
 asmlinkage void ret_from_fork(void);
 asmlinkage void ret_from_kernel_thread(void);
 
@@ -34,10 +40,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sw->r15;
 }
 
-int copy_thread(unsigned long clone_flags,
+int copy_thread_tls(unsigned long clone_flags,
                unsigned long usp,
                unsigned long kthread_arg,
-               struct task_struct *p)
+               struct task_struct *p,
+               unsigned long tls)
 {
        struct switch_stack *childstack;
        struct pt_regs *childregs = task_pt_regs(p);
@@ -64,7 +71,7 @@ int copy_thread(unsigned long clone_flags,
                        childregs->usp = usp;
                if (clone_flags & CLONE_SETTLS)
                        task_thread_info(p)->tp_value = childregs->tls
-                                                     = childregs->regs[0];
+                                                     = tls;
 
                childregs->a0 = 0;
                childstack->r15 = (unsigned long) ret_from_fork;
index 52eaf31ba27fc95a44f8e4ce377d776110ad1142..3821e55742f46f0070688f1e81161aefb8760f5c 100644 (file)
@@ -47,9 +47,6 @@ static void __init csky_memblock_init(void)
        signed long size;
 
        memblock_reserve(__pa(_stext), _end - _stext);
-#ifdef CONFIG_BLK_DEV_INITRD
-       memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
-#endif
 
        early_init_fdt_reserve_self();
        early_init_fdt_scan_reserved_mem();
@@ -133,6 +130,8 @@ void __init setup_arch(char **cmdline_p)
 
        sparse_init();
 
+       fixaddr_init();
+
 #ifdef CONFIG_HIGHMEM
        kmap_init();
 #endif
index b753d382e4cef53f45350e1108518096934d826a..0bb0954d557090c359b7e80bd30957ad0826b196 100644 (file)
@@ -120,7 +120,7 @@ void __init setup_smp_ipi(void)
        int rc;
 
        if (ipi_irq == 0)
-               panic("%s IRQ mapping failed\n", __func__);
+               return;
 
        rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt",
                                &ipi_dummy_dev);
index b5fc9447d93f2307f892ec0afa9fbda3e59a0294..52379d866fe45f2839afdcbca2216224fd455d33 100644 (file)
@@ -1,8 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
-#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
+#include <linux/of_clk.h>
 
 void __init time_init(void)
 {
index 2ff37beaf2bf38af39db8c44f58554e832f9909e..f05b413df32849f6000834e2445c1dbb194cdfc7 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <asm/vmlinux.lds.h>
 #include <asm/page.h>
+#include <asm/memory.h>
 
 OUTPUT_ARCH(csky)
 ENTRY(_start)
@@ -53,6 +54,54 @@ SECTIONS
        RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
        _edata = .;
 
+#ifdef CONFIG_HAVE_TCM
+       .tcm_start : {
+               . = ALIGN(PAGE_SIZE);
+               __tcm_start = .;
+       }
+
+       .text_data_tcm FIXADDR_TCM : AT(__tcm_start)
+       {
+               . = ALIGN(4);
+               __stcm_text_data = .;
+               *(.tcm.text)
+               *(.tcm.rodata)
+#ifndef CONFIG_HAVE_DTCM
+               *(.tcm.data)
+#endif
+               . = ALIGN(4);
+               __etcm_text_data = .;
+       }
+
+       . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_data_tcm);
+
+#ifdef CONFIG_HAVE_DTCM
+       #define ITCM_SIZE       CONFIG_ITCM_NR_PAGES * PAGE_SIZE
+
+       .dtcm_start : {
+               __dtcm_start = .;
+       }
+
+       .data_tcm FIXADDR_TCM + ITCM_SIZE : AT(__dtcm_start)
+       {
+               . = ALIGN(4);
+               __stcm_data = .;
+               *(.tcm.data)
+               . = ALIGN(4);
+               __etcm_data = .;
+       }
+
+       . = ADDR(.dtcm_start) + SIZEOF(.data_tcm);
+
+       .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_tcm)) {
+#else
+       .tcm_end : AT(ADDR(.tcm_start) + SIZEOF(.text_data_tcm)) {
+#endif
+               . = ALIGN(PAGE_SIZE);
+               __tcm_end = .;
+       }
+#endif
+
        EXCEPTION_TABLE(L1_CACHE_BYTES)
        BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES)
        VBR_BASE
index c94ef648109865e5662edeb1a61c9685426340fa..6e7696e55f71131dd1fde113ecdf177bbe01844c 100644 (file)
@@ -1,8 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 ifeq ($(CONFIG_CPU_HAS_CACHEV2),y)
 obj-y +=                       cachev2.o
+CFLAGS_REMOVE_cachev2.o = $(CC_FLAGS_FTRACE)
 else
 obj-y +=                       cachev1.o
+CFLAGS_REMOVE_cachev1.o = $(CC_FLAGS_FTRACE)
 endif
 
 obj-y +=                       dma-mapping.o
@@ -14,3 +16,4 @@ obj-y +=                      syscache.o
 obj-y +=                       tlb.o
 obj-y +=                       asid.o
 obj-y +=                       context.o
+obj-$(CONFIG_HAVE_TCM) +=      tcm.o
index 494ec912abff072ed0a85ba6d6c2b313a27001f2..5a5a9804a0e3d468baa2ff7444d91265d35f9783 100644 (file)
@@ -94,6 +94,11 @@ void icache_inv_all(void)
        cache_op_all(INS_CACHE|CACHE_INV, 0);
 }
 
+void local_icache_inv_all(void *priv)
+{
+       cache_op_all(INS_CACHE|CACHE_INV, 0);
+}
+
 void dcache_wb_range(unsigned long start, unsigned long end)
 {
        cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
index b61be6518e214bbed8d8704a6d36b76d1520f479..bc419f8039d3144ddaa14d7e9a1a6352869c9970 100644 (file)
@@ -3,15 +3,25 @@
 
 #include <linux/spinlock.h>
 #include <linux/smp.h>
+#include <linux/mm.h>
 #include <asm/cache.h>
 #include <asm/barrier.h>
 
-inline void dcache_wb_line(unsigned long start)
+#define INS_CACHE              (1 << 0)
+#define CACHE_INV              (1 << 4)
+
+void local_icache_inv_all(void *priv)
 {
-       asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
+       mtcr("cr17", INS_CACHE|CACHE_INV);
        sync_is();
 }
 
+void icache_inv_all(void)
+{
+       on_each_cpu(local_icache_inv_all, NULL, 1);
+}
+
+#ifdef CONFIG_CPU_HAS_ICACHE_INS
 void icache_inv_range(unsigned long start, unsigned long end)
 {
        unsigned long i = start & ~(L1_CACHE_BYTES - 1);
@@ -20,43 +30,32 @@ void icache_inv_range(unsigned long start, unsigned long end)
                asm volatile("icache.iva %0\n"::"r"(i):"memory");
        sync_is();
 }
-
-void icache_inv_all(void)
+#else
+void icache_inv_range(unsigned long start, unsigned long end)
 {
-       asm volatile("icache.ialls\n":::"memory");
-       sync_is();
+       icache_inv_all();
 }
+#endif
 
-void dcache_wb_range(unsigned long start, unsigned long end)
+inline void dcache_wb_line(unsigned long start)
 {
-       unsigned long i = start & ~(L1_CACHE_BYTES - 1);
-
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
+       asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
        sync_is();
 }
 
-void dcache_inv_range(unsigned long start, unsigned long end)
+void dcache_wb_range(unsigned long start, unsigned long end)
 {
        unsigned long i = start & ~(L1_CACHE_BYTES - 1);
 
        for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.civa %0\n"::"r"(i):"memory");
+               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
        sync_is();
 }
 
 void cache_wbinv_range(unsigned long start, unsigned long end)
 {
-       unsigned long i = start & ~(L1_CACHE_BYTES - 1);
-
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
-       sync_is();
-
-       i = start & ~(L1_CACHE_BYTES - 1);
-       for (; i < end; i += L1_CACHE_BYTES)
-               asm volatile("icache.iva %0\n"::"r"(i):"memory");
-       sync_is();
+       dcache_wb_range(start, end);
+       icache_inv_range(start, end);
 }
 EXPORT_SYMBOL(cache_wbinv_range);
 
index 3317b774f6dc145eae07b562689d975404279bb9..813129145f3da77c87a516f2f33bf48d8592ed18 100644 (file)
@@ -117,85 +117,29 @@ struct page *kmap_atomic_to_page(void *ptr)
        return pte_page(*pte);
 }
 
-static void __init fixrange_init(unsigned long start, unsigned long end,
-                               pgd_t *pgd_base)
+static void __init kmap_pages_init(void)
 {
-#ifdef CONFIG_HIGHMEM
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       int i, j, k;
        unsigned long vaddr;
-
-       vaddr = start;
-       i = __pgd_offset(vaddr);
-       j = __pud_offset(vaddr);
-       k = __pmd_offset(vaddr);
-       pgd = pgd_base + i;
-
-       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
-               pud = (pud_t *)pgd;
-               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
-                       pmd = (pmd_t *)pud;
-                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
-                               if (pmd_none(*pmd)) {
-                                       pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
-                                       if (!pte)
-                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
-                                                     __func__, PAGE_SIZE,
-                                                     PAGE_SIZE);
-
-                                       set_pmd(pmd, __pmd(__pa(pte)));
-                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
-                               }
-                               vaddr += PMD_SIZE;
-                       }
-                       k = 0;
-               }
-               j = 0;
-       }
-#endif
-}
-
-void __init fixaddr_kmap_pages_init(void)
-{
-       unsigned long vaddr;
-       pgd_t *pgd_base;
-#ifdef CONFIG_HIGHMEM
        pgd_t *pgd;
        pmd_t *pmd;
        pud_t *pud;
        pte_t *pte;
-#endif
-       pgd_base = swapper_pg_dir;
-
-       /*
-        * Fixed mappings:
-        */
-       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, 0, pgd_base);
-
-#ifdef CONFIG_HIGHMEM
-       /*
-        * Permanent kmaps:
-        */
+
        vaddr = PKMAP_BASE;
-       fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+       fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
 
        pgd = swapper_pg_dir + __pgd_offset(vaddr);
        pud = (pud_t *)pgd;
        pmd = pmd_offset(pud, vaddr);
        pte = pte_offset_kernel(pmd, vaddr);
        pkmap_page_table = pte;
-#endif
 }
 
 void __init kmap_init(void)
 {
        unsigned long vaddr;
 
-       fixaddr_kmap_pages_init();
+       kmap_pages_init();
 
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN);
 
index d4c2292ea46bc6cf0825c6af3b9499338577d329..cb64d8647a78b3eb9529b962e6267361e3c15897 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/pfn.h>
+#include <linux/initrd.h>
 
 #include <asm/setup.h>
 #include <asm/cachectl.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
+EXPORT_SYMBOL(invalid_pte_table);
 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
                                                __page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void __init setup_initrd(void)
+{
+       unsigned long size;
+
+       if (initrd_start >= initrd_end) {
+               pr_err("initrd not found or empty");
+               goto disable;
+       }
+
+       if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
+               pr_err("initrd extends beyond end of memory");
+               goto disable;
+       }
+
+       size = initrd_end - initrd_start;
+
+       if (memblock_is_region_reserved(__pa(initrd_start), size)) {
+               pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region",
+                      __pa(initrd_start), size);
+               goto disable;
+       }
+
+       memblock_reserve(__pa(initrd_start), size);
+
+       pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
+               (void *)(initrd_start), size);
+
+       initrd_below_start_ok = 1;
+
+       return;
+
+disable:
+       initrd_start = initrd_end = 0;
+
+       pr_err(" - disabling initrd\n");
+}
+#endif
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -46,6 +87,10 @@ void __init mem_init(void)
 #endif
        high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       setup_initrd();
+#endif
+
        memblock_free_all();
 
 #ifdef CONFIG_HIGHMEM
@@ -101,3 +146,50 @@ void __init pre_mmu_init(void)
        /* Setup page mask to 4k */
        write_mmu_pagemask(0);
 }
+
+void __init fixrange_init(unsigned long start, unsigned long end,
+                       pgd_t *pgd_base)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       int i, j, k;
+       unsigned long vaddr;
+
+       vaddr = start;
+       i = __pgd_offset(vaddr);
+       j = __pud_offset(vaddr);
+       k = __pmd_offset(vaddr);
+       pgd = pgd_base + i;
+
+       for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+               pud = (pud_t *)pgd;
+               for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+                       pmd = (pmd_t *)pud;
+                       for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+                               if (pmd_none(*pmd)) {
+                                       pte = (pte_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+                                       if (!pte)
+                                               panic("%s: Failed to allocate %lu bytes align=%lx\n",
+                                                     __func__, PAGE_SIZE,
+                                                     PAGE_SIZE);
+
+                                       set_pmd(pmd, __pmd(__pa(pte)));
+                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
+                               }
+                               vaddr += PMD_SIZE;
+                       }
+                       k = 0;
+               }
+               j = 0;
+       }
+}
+
+void __init fixaddr_init(void)
+{
+       unsigned long vaddr;
+
+       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+       fixrange_init(vaddr, vaddr + PMD_SIZE, swapper_pg_dir);
+}
index c4645e4e97f4b70d4cc23be29f20cd3aaaff5db0..ffade2f9a4c87914af5c8322fdfc1b9600a204c1 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/syscalls.h>
 #include <asm/page.h>
-#include <asm/cache.h>
+#include <asm/cacheflush.h>
 #include <asm/cachectl.h>
 
 SYSCALL_DEFINE3(cacheflush,
@@ -13,17 +13,14 @@ SYSCALL_DEFINE3(cacheflush,
 {
        switch (cache) {
        case ICACHE:
-               icache_inv_range((unsigned long)addr,
-                                (unsigned long)addr + bytes);
-               break;
+       case BCACHE:
+               flush_icache_mm_range(current->mm,
+                               (unsigned long)addr,
+                               (unsigned long)addr + bytes);
        case DCACHE:
                dcache_wb_range((unsigned long)addr,
                                (unsigned long)addr + bytes);
                break;
-       case BCACHE:
-               cache_wbinv_range((unsigned long)addr,
-                                 (unsigned long)addr + bytes);
-               break;
        default:
                return -EINVAL;
        }
diff --git a/arch/csky/mm/tcm.c b/arch/csky/mm/tcm.c
new file mode 100644 (file)
index 0000000..ddeb363
--- /dev/null
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/highmem.h>
+#include <linux/genalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+#if (CONFIG_ITCM_RAM_BASE == 0xffffffff)
+#error "You should define ITCM_RAM_BASE"
+#endif
+
+#ifdef CONFIG_HAVE_DTCM
+#if (CONFIG_DTCM_RAM_BASE == 0xffffffff)
+#error "You should define DTCM_RAM_BASE"
+#endif
+
+#if (CONFIG_DTCM_RAM_BASE == CONFIG_ITCM_RAM_BASE)
+#error "You should define correct DTCM_RAM_BASE"
+#endif
+#endif
+
+extern char __tcm_start, __tcm_end, __dtcm_start;
+
+static struct gen_pool *tcm_pool;
+
+static void __init tcm_mapping_init(void)
+{
+       pte_t *tcm_pte;
+       unsigned long vaddr, paddr;
+       int i;
+
+       paddr = CONFIG_ITCM_RAM_BASE;
+
+       if (pfn_valid(PFN_DOWN(CONFIG_ITCM_RAM_BASE)))
+               goto panic;
+
+#ifndef CONFIG_HAVE_DTCM
+       for (i = 0; i < TCM_NR_PAGES; i++) {
+#else
+       for (i = 0; i < CONFIG_ITCM_NR_PAGES; i++) {
+#endif
+               vaddr = __fix_to_virt(FIX_TCM - i);
+
+               tcm_pte =
+                       pte_offset_kernel((pmd_t *)pgd_offset_k(vaddr), vaddr);
+
+               set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
+
+               flush_tlb_one(vaddr);
+
+               paddr = paddr + PAGE_SIZE;
+       }
+
+#ifdef CONFIG_HAVE_DTCM
+       if (pfn_valid(PFN_DOWN(CONFIG_DTCM_RAM_BASE)))
+               goto panic;
+
+       paddr = CONFIG_DTCM_RAM_BASE;
+
+       for (i = 0; i < CONFIG_DTCM_NR_PAGES; i++) {
+               vaddr = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES - i);
+
+               tcm_pte =
+                       pte_offset_kernel((pmd_t *) pgd_offset_k(vaddr), vaddr);
+
+               set_pte(tcm_pte, pfn_pte(__phys_to_pfn(paddr), PAGE_KERNEL));
+
+               flush_tlb_one(vaddr);
+
+               paddr = paddr + PAGE_SIZE;
+       }
+#endif
+
+#ifndef CONFIG_HAVE_DTCM
+       memcpy((void *)__fix_to_virt(FIX_TCM),
+                               &__tcm_start, &__tcm_end - &__tcm_start);
+
+       pr_info("%s: mapping tcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
+
+       pr_info("%s: __tcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__tcm_start, &__tcm_end - &__tcm_start);
+#else
+       memcpy((void *)__fix_to_virt(FIX_TCM),
+                               &__tcm_start, &__dtcm_start - &__tcm_start);
+
+       pr_info("%s: mapping itcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM), CONFIG_ITCM_RAM_BASE);
+
+       pr_info("%s: __itcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__tcm_start, &__dtcm_start - &__tcm_start);
+
+       memcpy((void *)__fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
+                               &__dtcm_start, &__tcm_end - &__dtcm_start);
+
+       pr_info("%s: mapping dtcm va:0x%08lx to pa:0x%08x\n",
+                       __func__, __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES),
+                                               CONFIG_DTCM_RAM_BASE);
+
+       pr_info("%s: __dtcm_start va:0x%08lx size:%d\n",
+                       __func__, (unsigned long)&__dtcm_start, &__tcm_end - &__dtcm_start);
+
+#endif
+       return;
+panic:
+       panic("TCM init error");
+}
+
+void *tcm_alloc(size_t len)
+{
+       unsigned long vaddr;
+
+       if (!tcm_pool)
+               return NULL;
+
+       vaddr = gen_pool_alloc(tcm_pool, len);
+       if (!vaddr)
+               return NULL;
+
+       return (void *) vaddr;
+}
+EXPORT_SYMBOL(tcm_alloc);
+
+void tcm_free(void *addr, size_t len)
+{
+       gen_pool_free(tcm_pool, (unsigned long) addr, len);
+}
+EXPORT_SYMBOL(tcm_free);
+
+static int __init tcm_setup_pool(void)
+{
+#ifndef CONFIG_HAVE_DTCM
+       u32 pool_size = (u32) (TCM_NR_PAGES * PAGE_SIZE)
+                               - (u32) (&__tcm_end - &__tcm_start);
+
+       u32 tcm_pool_start = __fix_to_virt(FIX_TCM)
+                               + (u32) (&__tcm_end - &__tcm_start);
+#else
+       u32 pool_size = (u32) (CONFIG_DTCM_NR_PAGES * PAGE_SIZE)
+                               - (u32) (&__tcm_end - &__dtcm_start);
+
+       u32 tcm_pool_start = __fix_to_virt(FIX_TCM - CONFIG_ITCM_NR_PAGES)
+                               + (u32) (&__tcm_end - &__dtcm_start);
+#endif
+       int ret;
+
+       tcm_pool = gen_pool_create(2, -1);
+
+       ret = gen_pool_add(tcm_pool, tcm_pool_start, pool_size, -1);
+       if (ret) {
+               pr_err("%s: gen_pool add failed!\n", __func__);
+               return ret;
+       }
+
+       pr_info("%s: Added %d bytes @ 0x%08x to memory pool\n",
+               __func__, pool_size, tcm_pool_start);
+
+       return 0;
+}
+
+static int __init tcm_init(void)
+{
+       tcm_mapping_init();
+
+       tcm_setup_pool();
+
+       return 0;
+}
+arch_initcall(tcm_init);
index 5accda2767bea4d641116206dc470c8b34775a9b..a3301bab9231ae4a2f65859c5713f1b746b7239d 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 
 / {
        #address-cells = <1>;
                #clock-cells = <1>;
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4740-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4740_CLK_RTC>;
-               clock-names = "rtc";
-       };
-
        tcu: timer@10002000 {
                compatible = "ingenic,jz4740-tcu", "simple-mfd";
                reg = <0x10002000 0x1000>;
 
                interrupt-parent = <&intc>;
                interrupts = <23 22 21>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4740-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
index f928329b034b374de13a9d1e0570824a2e7d92c4..bb89653d16a321ab4bb9d136b96bff8eb8d0b2d0 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/dma/jz4780-dma.h>
 
 / {
 
                interrupt-parent = <&intc>;
                interrupts = <27 26 25>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4780-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
                status = "disabled";
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4780-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4780_CLK_RTCLK>;
-               clock-names = "rtc";
-       };
-
        nemc: nemc@13410000 {
                compatible = "ingenic,jz4780-nemc";
                reg = <0x13410000 0x10000>;
index 4994c695a1a73ba0bf0b4ca3dd5d3a4591ea75c7..147f7d5c243a2fe5c6cfc3a639f5e4c3299fa7ea 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/clock/x1000-cgu.h>
 #include <dt-bindings/dma/x1000-dma.h>
 
@@ -72,7 +73,7 @@
                        compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog";
                        reg = <0x0 0x10>;
 
-                       clocks = <&cgu X1000_CLK_RTCLK>;
+                       clocks = <&tcu TCU_CLK_WDT>;
                        clock-names = "wdt";
                };
        };
        i2c0: i2c-controller@10050000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10050000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c1: i2c-controller@10051000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10051000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c2: i2c-controller@10052000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10052000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
index 7c6a1095f556268700909ba31b5b24c1b6d9dc6a..aabd097933fe97f599361dd002d6e9f2fcdd999b 100644 (file)
  * effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
  * optimized memory barrier primitives."). Here we specify that the affected
  * sync instructions should be emitted twice.
+ * Note that this expression is evaluated by the assembler (not the compiler),
+ * and that the assembler evaluates '==' as 0 or -1, not 0 or 1.
  */
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-# define __SYNC_rpt(type)      (1 + (type == __SYNC_wmb))
+# define __SYNC_rpt(type)      (1 - (type == __SYNC_wmb))
 #else
 # define __SYNC_rpt(type)      1
 #endif
index 6176b9acba950e7189c48752498a9bb79f3648ad..d0d832ab3d3b86192b57c30f2c8c9e90820965ea 100644 (file)
@@ -134,7 +134,7 @@ void release_vpe(struct vpe *v)
 {
        list_del(&v->list);
        if (v->load_addr)
-               release_progmem(v);
+               release_progmem(v->load_addr);
        kfree(v);
 }
 
index aa89a41dc5dddef97aa080366aa47eb743dfe0eb..d7fe8408603e85583e013337e5df1c87d9ada7cb 100644 (file)
@@ -33,6 +33,7 @@ endif
 cflags-vdso := $(ccflags-vdso) \
        $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
        -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+       -mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
        -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
        $(call cc-option, -fno-asynchronous-unwind-tables) \
        $(call cc-option, -fno-stack-protector)
@@ -51,6 +52,8 @@ endif
 
 CFLAGS_REMOVE_vgettimeofday.o = -pg
 
+DISABLE_VDSO := n
+
 #
 # For the pre-R6 code in arch/mips/vdso/vdso.h for locating
 # the base address of VDSO, the linker will emit a R_MIPS_PC32
@@ -64,11 +67,24 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
 ifndef CONFIG_CPU_MIPSR6
   ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
     $(warning MIPS VDSO requires binutils >= 2.25)
-    obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
-    ccflags-vdso += -DDISABLE_MIPS_VDSO
+    DISABLE_VDSO := y
   endif
 endif
 
+#
+# GCC (at least up to version 9.2) appears to emit function calls that make use
+# of the GOT when targeting microMIPS, which we can't use in the VDSO due to
+# the lack of relocations. As such, we disable the VDSO for microMIPS builds.
+#
+ifdef CONFIG_CPU_MICROMIPS
+  DISABLE_VDSO := y
+endif
+
+ifeq ($(DISABLE_VDSO),y)
+  obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
+  ccflags-vdso += -DDISABLE_MIPS_VDSO
+endif
+
 # VDSO linker flags.
 VDSO_LDFLAGS := \
        -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
@@ -81,12 +97,18 @@ GCOV_PROFILE := n
 UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
+# Check that we don't have PIC 'jalr t9' calls left
+quiet_cmd_vdso_mips_check = VDSOCHK $@
+      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
+                      then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
+                            rm -f $@; /bin/false); fi
+
 #
 # Shared build commands.
 #
 
 quiet_cmd_vdsold_and_vdso_check = LD      $@
-      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check); $(cmd_vdso_mips_check)
 
 quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
index 86332080399a57d461c3a0efbd1ac2b3debeb9ab..080a0bf8e54bb9cd6267e38adacb2dc15150b401 100644 (file)
@@ -295,8 +295,13 @@ static inline bool pfn_valid(unsigned long pfn)
 /*
  * Some number of bits at the level of the page table that points to
  * a hugepte are used to encode the size.  This masks those bits.
+ * On 8xx, HW assistance requires 4k alignment for the hugepte.
  */
+#ifdef CONFIG_PPC_8xx
+#define HUGEPD_SHIFT_MASK     0xfff
+#else
 #define HUGEPD_SHIFT_MASK     0x3f
+#endif
 
 #ifndef __ASSEMBLY__
 
index 8387698bd5b629692fc676143e39202ed7b47f66..eedcbfb9a6ff38d874b027c2d639519b83ebba24 100644 (file)
@@ -168,6 +168,10 @@ struct thread_struct {
        unsigned long   srr1;
        unsigned long   dar;
        unsigned long   dsisr;
+#ifdef CONFIG_PPC_BOOK3S_32
+       unsigned long   r0, r3, r4, r5, r6, r8, r9, r11;
+       unsigned long   lr, ctr;
+#endif
 #endif
        /* Debug Registers */
        struct debug_reg debug;
index c25e562f1cd9d3f1d4fdf93b70bc2f698c2c4427..fcf24a365fc014b0490c957a16c8a9bfd55fc2fd 100644 (file)
@@ -132,6 +132,18 @@ int main(void)
        OFFSET(SRR1, thread_struct, srr1);
        OFFSET(DAR, thread_struct, dar);
        OFFSET(DSISR, thread_struct, dsisr);
+#ifdef CONFIG_PPC_BOOK3S_32
+       OFFSET(THR0, thread_struct, r0);
+       OFFSET(THR3, thread_struct, r3);
+       OFFSET(THR4, thread_struct, r4);
+       OFFSET(THR5, thread_struct, r5);
+       OFFSET(THR6, thread_struct, r6);
+       OFFSET(THR8, thread_struct, r8);
+       OFFSET(THR9, thread_struct, r9);
+       OFFSET(THR11, thread_struct, r11);
+       OFFSET(THLR, thread_struct, lr);
+       OFFSET(THCTR, thread_struct, ctr);
+#endif
 #endif
 #ifdef CONFIG_SPE
        OFFSET(THREAD_EVR0, thread_struct, evr[0]);
index a1eaffe868de4d76cbb8c401ddb175671e336ef4..7b048cee767c746fefe8a75cb991fb94fe757164 100644 (file)
@@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
                        eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
                        eeh_handle_normal_event(pe);
                } else {
+                       eeh_for_each_pe(pe, tmp_pe)
+                               eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
+                                       edev->mode &= ~EEH_DEV_NO_HANDLER;
+
+                       /* Notify all devices to be down */
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+                       eeh_set_channel_state(pe, pci_channel_io_perm_failure);
+                       eeh_pe_report(
+                               "error_detected(permanent failure)", pe,
+                               eeh_report_failure, NULL);
+
                        pci_lock_rescan_remove();
                        list_for_each_entry(hose, &hose_list, list_node) {
                                phb_pe = eeh_phb_pe_get(hose);
@@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
                                    (phb_pe->state & EEH_PE_RECOVERING))
                                        continue;
 
-                               eeh_for_each_pe(pe, tmp_pe)
-                                       eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
-                                               edev->mode &= ~EEH_DEV_NO_HANDLER;
-
-                               /* Notify all devices to be down */
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-                               eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-                               eeh_pe_report(
-                                       "error_detected(permanent failure)", pe,
-                                       eeh_report_failure, NULL);
                                bus = eeh_pe_bus_get(phb_pe);
                                if (!bus) {
                                        pr_err("%s: Cannot find PCI bus for "
index 0713daa651d9e469b2acedfea00d15f12ce6be70..16af0d8d90a8641ae2d43b29cef9d691a08f06e2 100644 (file)
@@ -783,7 +783,7 @@ fast_exception_return:
 1:     lis     r3,exc_exit_restart_end@ha
        addi    r3,r3,exc_exit_restart_end@l
        cmplw   r12,r3
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        bge     2b
 #else
        bge     3f
@@ -791,7 +791,7 @@ fast_exception_return:
        lis     r4,exc_exit_restart@ha
        addi    r4,r4,exc_exit_restart@l
        cmplw   r12,r4
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        blt     2b
 #else
        blt     3f
@@ -1354,12 +1354,17 @@ _GLOBAL(enter_rtas)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
        RFI
-1:     tophys(r9,r1)
+1:     tophys_novmstack r9, r1
+#ifdef CONFIG_VMAP_STACK
+       li      r0, MSR_KERNEL & ~MSR_IR        /* can take DTLB miss */
+       mtmsr   r0
+       isync
+#endif
        lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
        lwz     r9,8(r9)        /* original msr value */
        addi    r1,r1,INT_FRAME_SIZE
        li      r0,0
-       tophys(r7, r2)
+       tophys_novmstack r7, r2
        stw     r0, THREAD + RTAS_SP(r7)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
index 0493fcac6409508394932ea267e2f28c2f690f32..97c887950c3ca19d3156b8cc1e7aca6ceaef79f7 100644 (file)
@@ -290,17 +290,55 @@ MachineCheck:
 7:     EXCEPTION_PROLOG_2
        addi    r3,r1,STACK_FRAME_OVERHEAD
 #ifdef CONFIG_PPC_CHRP
-       bne     cr1,1f
+#ifdef CONFIG_VMAP_STACK
+       mfspr   r4, SPRN_SPRG_THREAD
+       tovirt(r4, r4)
+       lwz     r4, RTAS_SP(r4)
+       cmpwi   cr1, r4, 0
 #endif
-       EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1:     b       machine_check_in_rtas
+       beq     cr1, machine_check_tramp
+       b       machine_check_in_rtas
+#else
+       b       machine_check_tramp
 #endif
 
 /* Data access exception. */
        . = 0x300
        DO_KVM  0x300
 DataAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mfspr   r10, SPRN_SPRG_THREAD
+BEGIN_MMU_FTR_SECTION
+       stw     r11, THR11(r10)
+       mfspr   r10, SPRN_DSISR
+       mfcr    r11
+#ifdef CONFIG_PPC_KUAP
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
+#else
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
+#endif
+       mfspr   r10, SPRN_SPRG_THREAD
+       beq     hash_page_dsi
+.Lhash_page_dsi_cont:
+       mtcr    r11
+       lwz     r11, THR11(r10)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r11, SPRN_DAR
+       stw     r11, DAR(r10)
+       mfspr   r11, SPRN_DSISR
+       stw     r11, DSISR(r10)
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       b       handle_page_fault_tramp_1
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG handle_dar_dsisr=1
        get_and_save_dar_dsisr_on_stack r4, r5, r11
 BEGIN_MMU_FTR_SECTION
@@ -316,11 +354,32 @@ BEGIN_MMU_FTR_SECTION
 FTR_SECTION_ELSE
        b       handle_page_fault_tramp_2
 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 
 /* Instruction access exception. */
        . = 0x400
        DO_KVM  0x400
 InstructionAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+BEGIN_MMU_FTR_SECTION
+       andis.  r11, r11, SRR1_ISI_NOPT@h       /* no pte found? */
+       bne     hash_page_isi
+.Lhash_page_isi_cont:
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       EXCEPTION_PROLOG_2
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG
        andis.  r0,r9,SRR1_ISI_NOPT@h   /* no pte found? */
        beq     1f                      /* if so, try to put a PTE */
@@ -329,6 +388,7 @@ InstructionAccess:
 BEGIN_MMU_FTR_SECTION
        bl      hash_page
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 1:     mr      r4,r12
        andis.  r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
        stw     r4, _DAR(r11)
@@ -344,7 +404,7 @@ Alignment:
        EXCEPTION_PROLOG handle_dar_dsisr=1
        save_dar_dsisr_on_stack r4, r5, r11
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x600, alignment_exception)
+       b       alignment_exception_tramp
 
 /* Program check exception */
        EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
@@ -645,15 +705,100 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 
        . = 0x3000
 
+machine_check_tramp:
+       EXC_XFER_STD(0x200, machine_check_exception)
+
+alignment_exception_tramp:
+       EXC_XFER_STD(0x600, alignment_exception)
+
 handle_page_fault_tramp_1:
+#ifdef CONFIG_VMAP_STACK
+       EXCEPTION_PROLOG_2 handle_dar_dsisr=1
+#endif
        lwz     r4, _DAR(r11)
        lwz     r5, _DSISR(r11)
        /* fall through */
 handle_page_fault_tramp_2:
        EXC_XFER_LITE(0x300, handle_page_fault)
 
+#ifdef CONFIG_VMAP_STACK
+.macro save_regs_thread                thread
+       stw     r0, THR0(\thread)
+       stw     r3, THR3(\thread)
+       stw     r4, THR4(\thread)
+       stw     r5, THR5(\thread)
+       stw     r6, THR6(\thread)
+       stw     r8, THR8(\thread)
+       stw     r9, THR9(\thread)
+       mflr    r0
+       stw     r0, THLR(\thread)
+       mfctr   r0
+       stw     r0, THCTR(\thread)
+.endm
+
+.macro restore_regs_thread     thread
+       lwz     r0, THLR(\thread)
+       mtlr    r0
+       lwz     r0, THCTR(\thread)
+       mtctr   r0
+       lwz     r0, THR0(\thread)
+       lwz     r3, THR3(\thread)
+       lwz     r4, THR4(\thread)
+       lwz     r5, THR5(\thread)
+       lwz     r6, THR6(\thread)
+       lwz     r8, THR8(\thread)
+       lwz     r9, THR9(\thread)
+.endm
+
+hash_page_dsi:
+       save_regs_thread        r10
+       mfdsisr r3
+       mfdar   r4
+       mfsrr0  r5
+       mfsrr1  r9
+       rlwinm  r3, r3, 32 - 15, _PAGE_RW       /* DSISR_STORE -> _PAGE_RW */
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       b       .Lhash_page_dsi_cont
+
+hash_page_isi:
+       mr      r11, r10
+       mfspr   r10, SPRN_SPRG_THREAD
+       save_regs_thread        r10
+       li      r3, 0
+       lwz     r4, SRR0(r10)
+       lwz     r9, SRR1(r10)
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       mr      r10, r11
+       b       .Lhash_page_isi_cont
+
+       .globl fast_hash_page_return
+fast_hash_page_return:
+       andis.  r10, r9, SRR1_ISI_NOPT@h        /* Set on ISI, cleared on DSI */
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       bne     1f
+
+       /* DSI */
+       mtcr    r11
+       lwz     r11, THR11(r10)
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
+1:     /* ISI */
+       mtcr    r11
+       mfspr   r11, SPRN_SPRG_SCRATCH1
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
 stack_overflow:
        vmap_stack_overflow_exception
+#endif
 
 AltiVecUnavailable:
        EXCEPTION_PROLOG
index a6a5fbbf8504ae3cd5d5104076cec9358873dabb..9db162f79fe6e650fd61be32dd80bda9ea844f08 100644 (file)
 .endm
 
 .macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mtcr    r10
+FTR_SECTION_ELSE
+       stw     r10, _CCR(r11)
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#else
        stw     r10,_CCR(r11)           /* save registers */
+#endif
+       mfspr   r10, SPRN_SPRG_SCRATCH0
        stw     r12,GPR12(r11)
        stw     r9,GPR9(r11)
-       mfspr   r10,SPRN_SPRG_SCRATCH0
        stw     r10,GPR10(r11)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mfcr    r10
+       stw     r10, _CCR(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        mfspr   r12,SPRN_SPRG_SCRATCH1
        stw     r12,GPR11(r11)
        mflr    r10
        stw     r10, _DSISR(r11)
        .endif
        lwz     r9, SRR1(r12)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       andi.   r10, r9, MSR_PR
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        lwz     r12, SRR0(r12)
 #else
        mfspr   r12,SPRN_SRR0
index 9922306ae51244f9dcd0ed1f2f3ffac4603aabee..073a651787df8ab65847aa428fa1d9216d57a231 100644 (file)
@@ -256,7 +256,7 @@ InstructionTLBMiss:
         * set.  All other Linux PTE bits control the behavior
         * of the MMU.
         */
-       rlwimi  r10, r10, 0, 0x0f00     /* Clear bits 20-23 */
+       rlwinm  r10, r10, 0, ~0x0f00    /* Clear bits 20-23 */
        rlwimi  r10, r10, 4, 0x0400     /* Copy _PAGE_EXEC into bit 21 */
        ori     r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
        mtspr   SPRN_MI_RPN, r10        /* Update TLB entry */
index 0ffdd18b9f268b2b75f3c305505deb89fb6d09de..433d97bea1f3b8eb2e7554c317c9600a41d53b08 100644 (file)
@@ -166,7 +166,11 @@ BEGIN_FTR_SECTION
        mfspr   r9,SPRN_HID0
        andis.  r9,r9,HID0_NAP@h
        beq     1f
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_msscr0@ha
+#else
        addis   r9,r11,(nap_save_msscr0-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_msscr0@l(r9)
        mtspr   SPRN_MSSCR0, r9
        sync
@@ -174,7 +178,11 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
 BEGIN_FTR_SECTION
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_hid1@ha
+#else
        addis   r9,r11,(nap_save_hid1-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_hid1@l(r9)
        mtspr   SPRN_HID1, r9
 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
index e6c30cee6abf1748e52fe5a4ae9a0fbc01c3274a..d215f95545537ababac1eb849baab01df0e1642a 100644 (file)
@@ -200,14 +200,27 @@ unsigned long get_tm_stackpointer(struct task_struct *tsk)
         * normal/non-checkpointed stack pointer.
         */
 
+       unsigned long ret = tsk->thread.regs->gpr[1];
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        BUG_ON(tsk != current);
 
        if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+               preempt_disable();
                tm_reclaim_current(TM_CAUSE_SIGNAL);
                if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
-                       return tsk->thread.ckpt_regs.gpr[1];
+                       ret = tsk->thread.ckpt_regs.gpr[1];
+
+               /*
+                * If we treclaim, we must clear the current thread's TM bits
+                * before re-enabling preemption. Otherwise we might be
+                * preempted and have the live MSR[TS] changed behind our back
+                * (tm_recheckpoint_new_task() would recheckpoint). Besides, we
+                * enter the signal handler in non-transactional state.
+                */
+               tsk->thread.regs->msr &= ~MSR_TS_MASK;
+               preempt_enable();
        }
 #endif
-       return tsk->thread.regs->gpr[1];
+       return ret;
 }
index 98600b276f764d957fe5f8d91386c921a288cc90..1b090a76b4444729c4b8614b72277c1643539e92 100644 (file)
@@ -489,19 +489,11 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
  */
 static int save_tm_user_regs(struct pt_regs *regs,
                             struct mcontext __user *frame,
-                            struct mcontext __user *tm_frame, int sigret)
+                            struct mcontext __user *tm_frame, int sigret,
+                            unsigned long msr)
 {
-       unsigned long msr = regs->msr;
-
        WARN_ON(tm_suspend_disabled);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
        /* Save both sets of general registers */
        if (save_general_regs(&current->thread.ckpt_regs, frame)
            || save_general_regs(regs, tm_frame))
@@ -912,6 +904,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -944,13 +940,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_frame = &rt_sf->uc_transact.uc_mcontext;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (__put_user((unsigned long)&rt_sf->uc_transact,
                               &rt_sf->uc.uc_link) ||
                    __put_user((unsigned long)tm_frame,
                               &rt_sf->uc_transact.uc_regs))
                        goto badframe;
-               if (save_tm_user_regs(regs, frame, tm_frame, sigret))
+               if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
                        goto badframe;
        }
        else
@@ -1369,6 +1365,10 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -1402,9 +1402,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->mctx_transact;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
-                                     sigret))
+                                     sigret, msr))
                        goto badframe;
        }
        else
index 117515564ec7a6e2d13ecdeba37e3973934fba10..84ed2e77ef9c3f5e039cf8f65921b5124e0bb226 100644 (file)
@@ -192,7 +192,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
                                 struct sigcontext __user *tm_sc,
                                 struct task_struct *tsk,
-                                int signr, sigset_t *set, unsigned long handler)
+                                int signr, sigset_t *set, unsigned long handler,
+                                unsigned long msr)
 {
        /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
         * process never used altivec yet (MSR_VEC is zero in pt_regs of
@@ -207,12 +208,11 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
        elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
 #endif
        struct pt_regs *regs = tsk->thread.regs;
-       unsigned long msr = tsk->thread.regs->msr;
        long err = 0;
 
        BUG_ON(tsk != current);
 
-       BUG_ON(!MSR_TM_ACTIVE(regs->msr));
+       BUG_ON(!MSR_TM_ACTIVE(msr));
 
        WARN_ON(tm_suspend_disabled);
 
@@ -222,13 +222,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
         */
        msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
 #ifdef CONFIG_ALTIVEC
        err |= __put_user(v_regs, &sc->v_regs);
        err |= __put_user(tm_v_regs, &tm_sc->v_regs);
@@ -824,6 +817,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        unsigned long newsp = 0;
        long err = 0;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -841,7 +838,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                /* The ucontext_t passed to userland points to the second
                 * ucontext_t (for transactional state) with its uc_link ptr.
                 */
@@ -849,7 +846,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
                err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
                                            &frame->uc_transact.uc_mcontext,
                                            tsk, ksig->sig, NULL,
-                                           (unsigned long)ksig->ka.sa.sa_handler);
+                                           (unsigned long)ksig->ka.sa.sa_handler,
+                                           msr);
        } else
 #endif
        {
index c11b0a005196675271839c20a9a0c89cf2253f13..2015c4f962380940700d84bcc32af9d4961b80ea 100644 (file)
 #include <asm/feature-fixups.h>
 #include <asm/code-patching-asm.h>
 
-#ifdef CONFIG_VMAP_STACK
-#define ADDR_OFFSET    0
-#else
-#define ADDR_OFFSET    PAGE_OFFSET
-#endif
-
 #ifdef CONFIG_SMP
        .section .bss
        .align  2
@@ -53,8 +47,8 @@ mmu_hash_lock:
        .text
 _GLOBAL(hash_page)
 #ifdef CONFIG_SMP
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@h
-       ori     r8, r8, (mmu_hash_lock - ADDR_OFFSET)@l
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@h
+       ori     r8, r8, (mmu_hash_lock - PAGE_OFFSET)@l
        lis     r0,0x0fff
        b       10f
 11:    lwz     r6,0(r8)
@@ -72,12 +66,9 @@ _GLOBAL(hash_page)
        cmplw   0,r4,r0
        ori     r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
        mfspr   r5, SPRN_SPRG_PGDIR     /* phys page-table root */
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r5, r5)
-#endif
        blt+    112f                    /* assume user more likely */
-       lis     r5, (swapper_pg_dir - ADDR_OFFSET)@ha   /* if kernel address, use */
-       addi    r5 ,r5 ,(swapper_pg_dir - ADDR_OFFSET)@l        /* kernel page table */
+       lis     r5, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
+       addi    r5 ,r5 ,(swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
        rlwimi  r3,r9,32-12,29,29       /* MSR_PR -> _PAGE_USER */
 112:
 #ifndef CONFIG_PTE_64BIT
@@ -89,9 +80,6 @@ _GLOBAL(hash_page)
        lwzx    r8,r8,r5                /* Get L1 entry */
        rlwinm. r8,r8,0,0,20            /* extract pt base address */
 #endif
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r8, r8)
-#endif
 #ifdef CONFIG_SMP
        beq-    hash_page_out           /* return if no mapping */
 #else
@@ -143,30 +131,36 @@ retry:
        bne-    retry                   /* retry if someone got there first */
 
        mfsrin  r3,r4                   /* get segment reg for segment */
+#ifndef CONFIG_VMAP_STACK
        mfctr   r0
        stw     r0,_CTR(r11)
+#endif
        bl      create_hpte             /* add the hash table entry */
 
 #ifdef CONFIG_SMP
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
 #endif
 
+#ifdef CONFIG_VMAP_STACK
+       b       fast_hash_page_return
+#else
        /* Return from the exception */
        lwz     r5,_CTR(r11)
        mtctr   r5
        lwz     r0,GPR0(r11)
        lwz     r8,GPR8(r11)
        b       fast_exception_return
+#endif
 
 #ifdef CONFIG_SMP
 hash_page_out:
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
        blr
 #endif /* CONFIG_SMP */
 
@@ -341,7 +335,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        patch_site      1f, patch__hash_page_A1
        patch_site      2f, patch__hash_page_A2
        /* Get the address of the primary PTE group in the hash table (r3) */
-0:     lis     r0, (Hash_base - ADDR_OFFSET)@h /* base address of hash table */
+0:     lis     r0, (Hash_base - PAGE_OFFSET)@h /* base address of hash table */
 1:     rlwimi  r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
 2:     rlwinm  r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
        xor     r3,r3,r0                /* make primary hash */
@@ -355,10 +349,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    10f                     /* no PTE: go look for an empty slot */
        tlbie   r4
 
-       lis     r4, (htab_hash_searches - ADDR_OFFSET)@ha
-       lwz     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       lis     r4, (htab_hash_searches - PAGE_OFFSET)@ha
+       lwz     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1                 /* count how many searches we do */
-       stw     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       stw     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
 
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        mtctr   r0
@@ -390,10 +384,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    found_empty
 
        /* update counter of times that the primary PTEG is full */
-       lis     r4, (primary_pteg_full - ADDR_OFFSET)@ha
-       lwz     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       lis     r4, (primary_pteg_full - PAGE_OFFSET)@ha
+       lwz     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1
-       stw     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       stw     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
 
        patch_site      0f, patch__hash_page_C
        /* Search the secondary PTEG for an empty slot */
@@ -427,8 +421,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
         * lockup here but that shouldn't happen
         */
 
-1:     lis     r4, (next_slot - ADDR_OFFSET)@ha        /* get next evict slot */
-       lwz     r6, (next_slot - ADDR_OFFSET)@l(r4)
+1:     lis     r4, (next_slot - PAGE_OFFSET)@ha        /* get next evict slot */
+       lwz     r6, (next_slot - PAGE_OFFSET)@l(r4)
        addi    r6,r6,HPTE_SIZE                 /* search for candidate */
        andi.   r6,r6,7*HPTE_SIZE
        stw     r6,next_slot@l(r4)
index 0a1c65a2c56553cf36836af6bc30ef2424489980..f888cbb109b9134daee3176b37988b250ef008f5 100644 (file)
@@ -413,7 +413,7 @@ void __init MMU_init_hw(void)
 void __init MMU_init_hw_patch(void)
 {
        unsigned int hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
-       unsigned int hash;
+       unsigned int hash = (unsigned int)Hash - PAGE_OFFSET;
 
        if (ppc_md.progress)
                ppc_md.progress("hash:patch", 0x345);
@@ -425,11 +425,6 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:create_hpte
         */
-       if (IS_ENABLED(CONFIG_VMAP_STACK))
-               hash = (unsigned int)Hash;
-       else
-               hash = (unsigned int)Hash - PAGE_OFFSET;
-
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__hash_page_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__hash_page_A2, 0x7c0, hash_mb2 << 6);
@@ -439,8 +434,7 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:flush_hash_page
         */
-       modify_instruction_site(&patch__flush_hash_A0, 0xffff,
-                               ((unsigned int)Hash - PAGE_OFFSET) >> 16);
+       modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__flush_hash_A2, 0x7c0, hash_mb2 << 6);
        modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);
index 73d4873fc7f85442eafc08399446bc176fd82b9a..33b3461d91e8db0e7b19f569a5c20d06a9a827be 100644 (file)
@@ -53,20 +53,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (pshift >= pdshift) {
                cachep = PGT_CACHE(PTE_T_ORDER);
                num_hugepd = 1 << (pshift - pdshift);
+               new = NULL;
        } else if (IS_ENABLED(CONFIG_PPC_8xx)) {
-               cachep = PGT_CACHE(PTE_INDEX_SIZE);
+               cachep = NULL;
                num_hugepd = 1;
+               new = pte_alloc_one(mm);
        } else {
                cachep = PGT_CACHE(pdshift - pshift);
                num_hugepd = 1;
+               new = NULL;
        }
 
-       if (!cachep) {
+       if (!cachep && !new) {
                WARN_ONCE(1, "No page table cache created for hugetlb tables");
                return -ENOMEM;
        }
 
-       new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
+       if (cachep)
+               new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -97,7 +101,10 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (i < num_hugepd) {
                for (i = i - 1 ; i >= 0; i--, hpdp--)
                        *hpdp = __hugepd(0);
-               kmem_cache_free(cachep, new);
+               if (cachep)
+                       kmem_cache_free(cachep, new);
+               else
+                       pte_free(mm, new);
        } else {
                kmemleak_ignore(new);
        }
@@ -324,8 +331,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
        else if (IS_ENABLED(CONFIG_PPC_8xx))
-               pgtable_free_tlb(tlb, hugepte,
-                                get_hugepd_cache_index(PTE_INDEX_SIZE));
+               pgtable_free_tlb(tlb, hugepte, 0);
        else
                pgtable_free_tlb(tlb, hugepte,
                                 get_hugepd_cache_index(pdshift - shift));
@@ -639,12 +645,13 @@ static int __init hugetlbpage_init(void)
                 * if we have pdshift and shift value same, we don't
                 * use pgt cache for hugepd.
                 */
-               if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
-                       pgtable_cache_add(PTE_INDEX_SIZE);
-               else if (pdshift > shift)
-                       pgtable_cache_add(pdshift - shift);
-               else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
+               if (pdshift > shift) {
+                       if (!IS_ENABLED(CONFIG_PPC_8xx))
+                               pgtable_cache_add(pdshift - shift);
+               } else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
+                          IS_ENABLED(CONFIG_PPC_8xx)) {
                        pgtable_cache_add(PTE_T_ORDER);
+               }
 
                configured = true;
        }
index 16dd95bd0749d851410fce5ae727a0e9edfdb563..db5664dde5ff9d9d6a461eb1ed25a2d0f11e3d8e 100644 (file)
@@ -185,8 +185,7 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
 
 static void __init kasan_early_hash_table(void)
 {
-       unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
-                                                           __pa(early_hash);
+       unsigned int hash = __pa(early_hash);
 
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
index e8c84d265602bc57bf47b49243a2044d93f2336d..0ec9640335bb3544548bcf3c391b2dd946621f4b 100644 (file)
@@ -3435,6 +3435,11 @@ getstring(char *s, int size)
        int c;
 
        c = skipbl();
+       if (c == '\n') {
+               *s = 0;
+               return;
+       }
+
        do {
                if( size > 1 ){
                        *s++ = c;
index 8dab0bb6ae667c5f89da8aca74a0a3bb61dcfaa9..8a45a37d2af4ccf129e4de4002529c853b224d8a 100644 (file)
@@ -1,2 +1,4 @@
 Image
 Image.gz
+loader
+loader.lds
index 435b65532e2945703cc17a9e5c4f7613a0d5b6b8..8e18d2c64399df91e0619852bfd5c9a4757cdc37 100644 (file)
 #define EXC_LOAD_PAGE_FAULT    13
 #define EXC_STORE_PAGE_FAULT   15
 
+/* PMP configuration */
+#define PMP_R                  0x01
+#define PMP_W                  0x02
+#define PMP_X                  0x04
+#define PMP_A                  0x18
+#define PMP_A_TOR              0x08
+#define PMP_A_NA4              0x10
+#define PMP_A_NAPOT            0x18
+#define PMP_L                  0x80
+
 /* symbolic CSR names: */
 #define CSR_CYCLE              0xc00
 #define CSR_TIME               0xc01
 #define CSR_MCAUSE             0x342
 #define CSR_MTVAL              0x343
 #define CSR_MIP                        0x344
+#define CSR_PMPCFG0            0x3a0
+#define CSR_PMPADDR0           0x3b0
 #define CSR_MHARTID            0xf14
 
 #ifdef CONFIG_RISCV_M_MODE
index 271860fc2c3f02a5d50552339a005004444ab456..85f2073e7fe4abee5dcb97f91cd2f07cf9d9f9e7 100644 (file)
@@ -58,6 +58,12 @@ _start_kernel:
        /* Reset all registers except ra, a0, a1 */
        call reset_regs
 
+       /* Setup a PMP to permit access to all of memory. */
+       li a0, -1
+       csrw CSR_PMPADDR0, a0
+       li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
+       csrw CSR_PMPCFG0, a0
+
        /*
         * The hartid in a0 is expected later on, and we have no firmware
         * to hand it to us.
index f4cad5163bf2c0160f64e828ba07e2d3b84623d2..ffb3d94bf0cc2782f5777e1423f6a3fc4310099f 100644 (file)
@@ -156,6 +156,6 @@ void __init trap_init(void)
        csr_write(CSR_SCRATCH, 0);
        /* Set the exception vector address */
        csr_write(CSR_TVEC, &handle_exception);
-       /* Enable all interrupts */
-       csr_write(CSR_IE, -1);
+       /* Enable interrupts */
+       csr_write(CSR_IE, IE_SIE | IE_EIE);
 }
index f0cc860405871d0457d6dc0fdc83fb3a0350a2c5..ec0ca90dd9000f339a3d8a739d59e84df386d0dc 100644 (file)
@@ -19,18 +19,20 @@ asmlinkage void __init kasan_early_init(void)
        for (i = 0; i < PTRS_PER_PTE; ++i)
                set_pte(kasan_early_shadow_pte + i,
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       PAGE_KERNEL));
+                              PAGE_KERNEL));
 
        for (i = 0; i < PTRS_PER_PMD; ++i)
                set_pmd(kasan_early_shadow_pmd + i,
-                pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pmd(PFN_DOWN
+                               (__pa((uintptr_t) kasan_early_shadow_pte)),
+                               __pgprot(_PAGE_TABLE)));
 
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        /* init for swapper_pg_dir */
        pgd = pgd_offset_k(KASAN_SHADOW_START);
@@ -38,37 +40,43 @@ asmlinkage void __init kasan_early_init(void)
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
 }
 
 static void __init populate(void *start, void *end)
 {
-       unsigned long i;
+       unsigned long i, offset;
        unsigned long vaddr = (unsigned long)start & PAGE_MASK;
        unsigned long vend = PAGE_ALIGN((unsigned long)end);
        unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
+       unsigned long n_ptes =
+           ((n_pages + PTRS_PER_PTE) & -PTRS_PER_PTE) / PTRS_PER_PTE;
        unsigned long n_pmds =
-               (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 :
-                                               n_pages / PTRS_PER_PTE;
+           ((n_ptes + PTRS_PER_PMD) & -PTRS_PER_PMD) / PTRS_PER_PMD;
+
+       pte_t *pte =
+           memblock_alloc(n_ptes * PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
+       pmd_t *pmd =
+           memblock_alloc(n_pmds * PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
        pgd_t *pgd = pgd_offset_k(vaddr);
-       pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
-       pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; i++) {
                phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
-
-               set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
+               set_pte(&pte[i], pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
        }
 
-       for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD)
-               set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))),
+       for (i = 0, offset = 0; i < n_ptes; i++, offset += PTRS_PER_PTE)
+               set_pmd(&pmd[i],
+                       pfn_pmd(PFN_DOWN(__pa(&pte[offset])),
                                __pgprot(_PAGE_TABLE)));
 
-       for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE)
-               set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))),
+       for (i = 0, offset = 0; i < n_pmds; i++, offset += PTRS_PER_PMD)
+               set_pgd(&pgd[i],
+                       pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
                                __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
@@ -81,7 +89,8 @@ void __init kasan_init(void)
        unsigned long i;
 
        kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
-                       (void *)kasan_mem_to_shadow((void *)VMALLOC_END));
+                                   (void *)kasan_mem_to_shadow((void *)
+                                                               VMALLOC_END));
 
        for_each_memblock(memory, reg) {
                void *start = (void *)__va(reg->base);
@@ -90,14 +99,14 @@ void __init kasan_init(void)
                if (start >= end)
                        break;
 
-               populate(kasan_mem_to_shadow(start),
-                        kasan_mem_to_shadow(end));
+               populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
        };
 
        for (i = 0; i < PTRS_PER_PTE; i++)
                set_pte(&kasan_early_shadow_pte[i],
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED)));
+                              __pgprot(_PAGE_PRESENT | _PAGE_READ |
+                                       _PAGE_ACCESSED)));
 
        memset(kasan_early_shadow_page, 0, PAGE_SIZE);
        init_task.kasan_depth = 0;
index e0e3a465bbfd6fd15eb44ab8675af10c171c2e01..8dfa2cf1f05c7a9028683aa1900e0975d27863e9 100644 (file)
@@ -146,7 +146,7 @@ all: bzImage
 #KBUILD_IMAGE is necessary for packaging targets like rpm-pkg, deb-pkg...
 KBUILD_IMAGE   := $(boot)/bzImage
 
-install: vmlinux
+install:
        $(Q)$(MAKE) $(build)=$(boot) $@
 
 bzImage: vmlinux
index 30f1811540c5e7820d2497ab9e6cf5fffc94f06d..45b33b83de08c7e0458afe43768c4dd102e2e625 100644 (file)
@@ -70,7 +70,7 @@ $(obj)/compressed/vmlinux: $(obj)/startup.a FORCE
 $(obj)/startup.a: $(OBJECTS) FORCE
        $(call if_changed,ar)
 
-install: $(CONFIGURE) $(obj)/bzImage
+install:
        sh -x  $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
              System.map "$(INSTALL_PATH)"
 
index 5d12352545c558d4f5598fd074048029cfd6218a..5591243d673e82cea561c5df4c9e6ac19c55ed6f 100644 (file)
@@ -75,7 +75,7 @@ static unsigned long get_random(unsigned long limit)
                *(unsigned long *) prng.parm_block ^= seed;
                for (i = 0; i < 16; i++) {
                        cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
-                                 (char *) entropy, (char *) entropy,
+                                 (u8 *) entropy, (u8 *) entropy,
                                  sizeof(entropy));
                        memcpy(prng.parm_block, entropy, sizeof(entropy));
                }
index 2e60c80395ab084afbe4713fbc8816f42bea3f60..0c86ba19fa2bcdb0ca9ce4627366b59714b379eb 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -474,7 +475,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -684,7 +684,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -748,7 +747,6 @@ CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
 CONFIG_HEADERS_INSTALL=y
-CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
@@ -772,9 +770,9 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_PANIC_ON_OOPS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_ON_OOPS=y
 CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -783,9 +781,20 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
+CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_NOTIFIER_ERROR_INJECTION=m
 CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
@@ -796,15 +805,6 @@ CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_LATENCYTOP=y
-CONFIG_IRQSOFF_TRACER=y
-CONFIG_PREEMPT_TRACER=y
-CONFIG_SCHED_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
-CONFIG_HIST_TRIGGERS=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_TEST_SORT=y
@@ -814,5 +814,3 @@ CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 25f79984958219506566216ca4a34db0e49a31e4..6b27d861a9a306e03cb7f319339cabf16a0c6de3 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -470,7 +471,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -677,7 +677,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -739,18 +738,18 @@ CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
 CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 61115913a2c714969d14a9206a9f82b2e8965400..d6bcd34f3ec329c5cb5603254c470d900d650839 100644 (file)
@@ -344,7 +344,7 @@ struct kvm_s390_sie_block {
        __u64   itdba;                  /* 0x01e8 */
        __u64   riccbd;                 /* 0x01f0 */
        __u64   gvrd;                   /* 0x01f8 */
-} __attribute__((packed));
+} __packed __aligned(512);
 
 struct kvm_s390_itdb {
        __u8    data[256];
index 4ebcf891ff3c256bde5bd4a34d77d73c4c7df5f0..62440a82731ae69476a9ed84f77dca1c81410d07 100644 (file)
@@ -42,7 +42,7 @@ void __storage_key_init_range(unsigned long start, unsigned long end);
 
 static inline void storage_key_init_range(unsigned long start, unsigned long end)
 {
-       if (PAGE_DEFAULT_KEY)
+       if (PAGE_DEFAULT_KEY != 0)
                __storage_key_init_range(start, end);
 }
 
index 361ef5eda46895270f781407cbd684dd5eb1ac1e..aadb3d0e2adc767c862f4455a6a9c3949691b856 100644 (file)
@@ -84,7 +84,6 @@ void s390_update_cpu_mhz(void);
 void cpu_detect_mhz_feature(void);
 
 extern const struct seq_operations cpuinfo_op;
-extern int sysctl_ieee_emulation_warnings;
 extern void execve_tail(void);
 extern void __bpon(void);
 
index 71e3f0146cda084920c40b7736c01d45e5b0a594..1e3517b0518beb27d8dc7e2d7ea2b378d4f36993 100644 (file)
@@ -201,7 +201,7 @@ struct slib {
  * @scount: SBAL count
  * @sflags: whole SBAL flags
  * @length: length
- * @addr: address
+ * @addr: absolute data address
 */
 struct qdio_buffer_element {
        u8 eflags;
@@ -211,7 +211,7 @@ struct qdio_buffer_element {
        u8 scount;
        u8 sflags;
        u32 length;
-       void *addr;
+       u64 addr;
 } __attribute__ ((packed, aligned(16)));
 
 /**
@@ -227,7 +227,7 @@ struct qdio_buffer {
  * @sbal: absolute SBAL address
  */
 struct sl_element {
-       unsigned long sbal;
+       u64 sbal;
 } __attribute__ ((packed));
 
 /**
index 07d30ffcfa4129522ae0592ccd57e5c0e65b97bd..47a67a958107e2e2e6f8e1ea8ad795f1e318ec3b 100644 (file)
@@ -505,7 +505,7 @@ static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
                switch (prot) {
                case PROT_TYPE_IEP:
                        tec->b61 = 1;
-                       /* FALL THROUGH */
+                       fallthrough;
                case PROT_TYPE_LA:
                        tec->b56 = 1;
                        break;
@@ -514,12 +514,12 @@ static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
                        break;
                case PROT_TYPE_ALC:
                        tec->b60 = 1;
-                       /* FALL THROUGH */
+                       fallthrough;
                case PROT_TYPE_DAT:
                        tec->b61 = 1;
                        break;
                }
-               /* FALL THROUGH */
+               fallthrough;
        case PGM_ASCE_TYPE:
        case PGM_PAGE_TRANSLATION:
        case PGM_REGION_FIRST_TRANS:
@@ -534,7 +534,7 @@ static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
                tec->addr = gva >> PAGE_SHIFT;
                tec->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH;
                tec->as = psw_bits(vcpu->arch.sie_block->gpsw).as;
-               /* FALL THROUGH */
+               fallthrough;
        case PGM_ALEN_TRANSLATION:
        case PGM_ALE_SEQUENCE:
        case PGM_ASTE_VALIDITY:
@@ -677,7 +677,7 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
                        dat_protection |= rfte.p;
                ptr = rfte.rto * PAGE_SIZE + vaddr.rsx * 8;
        }
-               /* fallthrough */
+               fallthrough;
        case ASCE_TYPE_REGION2: {
                union region2_table_entry rste;
 
@@ -695,7 +695,7 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
                        dat_protection |= rste.p;
                ptr = rste.rto * PAGE_SIZE + vaddr.rtx * 8;
        }
-               /* fallthrough */
+               fallthrough;
        case ASCE_TYPE_REGION3: {
                union region3_table_entry rtte;
 
@@ -723,7 +723,7 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
                        dat_protection |= rtte.fc0.p;
                ptr = rtte.fc0.sto * PAGE_SIZE + vaddr.sx * 8;
        }
-               /* fallthrough */
+               fallthrough;
        case ASCE_TYPE_SEGMENT: {
                union segment_table_entry ste;
 
@@ -1050,7 +1050,8 @@ shadow_r2t:
                rc = gmap_shadow_r2t(sg, saddr, rfte.val, *fake);
                if (rc)
                        return rc;
-       } /* fallthrough */
+       }
+               fallthrough;
        case ASCE_TYPE_REGION2: {
                union region2_table_entry rste;
 
@@ -1076,7 +1077,8 @@ shadow_r3t:
                rc = gmap_shadow_r3t(sg, saddr, rste.val, *fake);
                if (rc)
                        return rc;
-       } /* fallthrough */
+       }
+               fallthrough;
        case ASCE_TYPE_REGION3: {
                union region3_table_entry rtte;
 
@@ -1111,7 +1113,8 @@ shadow_sgt:
                rc = gmap_shadow_sgt(sg, saddr, rtte.val, *fake);
                if (rc)
                        return rc;
-       } /* fallthrough */
+       }
+               fallthrough;
        case ASCE_TYPE_SEGMENT: {
                union segment_table_entry ste;
 
index 028167d6eacdd53fddfc7ada3952a90f3884deed..8191106bf7b92dcf99caec72516b18b8c9212691 100644 (file)
@@ -886,7 +886,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        case PGM_PRIMARY_AUTHORITY:
        case PGM_SECONDARY_AUTHORITY:
                nullifying = true;
-               /* fall through */
+               fallthrough;
        case PGM_SPACE_SWITCH:
                rc = put_guest_lc(vcpu, pgm_info.trans_exc_code,
                                  (u64 *)__LC_TRANS_EXC_CODE);
index 807ed6d722dd9551049fa6f02e047f69279ce42d..6b2649b3d4f326a6f8e8cb1b2080d6088809aa2c 100644 (file)
@@ -2002,6 +2002,9 @@ static int kvm_s390_get_cmma(struct kvm *kvm, struct kvm_s390_cmma_log *args,
        struct kvm_memslots *slots = kvm_memslots(kvm);
        struct kvm_memory_slot *ms;
 
+       if (unlikely(!slots->used_slots))
+               return 0;
+
        cur_gfn = kvm_s390_next_dirty_cmma(slots, args->start_gfn);
        ms = gfn_to_memslot(kvm, cur_gfn);
        args->count = 0;
@@ -3743,7 +3746,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                rc = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_OPR_LOAD);
                break;
        case KVM_MP_STATE_CHECK_STOP:
-               /* fall through - CHECK_STOP and LOAD are not supported yet */
+               fallthrough;    /* CHECK_STOP and LOAD are not supported yet */
        default:
                rc = -ENXIO;
        }
@@ -4970,7 +4973,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                                        old->npages * PAGE_SIZE);
                if (rc)
                        break;
-               /* FALLTHROUGH */
+               fallthrough;
        case KVM_MR_CREATE:
                rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
                                      mem->guest_phys_addr, mem->memory_size);
index 27926a06df32a3930b6e73519dab682b5be07b17..2fbece47ef6fd3d713d714eeaffb2d921fb53091 100644 (file)
@@ -804,7 +804,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
                if (*table & _REGION_ENTRY_INVALID)
                        return NULL;
                table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-               /* Fallthrough */
+               fallthrough;
        case _ASCE_TYPE_REGION2:
                table += (gaddr & _REGION2_INDEX) >> _REGION2_SHIFT;
                if (level == 3)
@@ -812,7 +812,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
                if (*table & _REGION_ENTRY_INVALID)
                        return NULL;
                table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-               /* Fallthrough */
+               fallthrough;
        case _ASCE_TYPE_REGION3:
                table += (gaddr & _REGION3_INDEX) >> _REGION3_SHIFT;
                if (level == 2)
@@ -820,7 +820,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
                if (*table & _REGION_ENTRY_INVALID)
                        return NULL;
                table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-               /* Fallthrough */
+               fallthrough;
        case _ASCE_TYPE_SEGMENT:
                table += (gaddr & _SEGMENT_INDEX) >> _SEGMENT_SHIFT;
                if (level == 1)
@@ -2552,12 +2552,13 @@ int gmap_mark_unmergeable(void)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
+       int ret;
 
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
-               if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
-                               MADV_UNMERGEABLE, &vma->vm_flags)) {
-                       return -ENOMEM;
-               }
+               ret = ksm_madvise(vma, vma->vm_start, vma->vm_end,
+                                 MADV_UNMERGEABLE, &vma->vm_flags);
+               if (ret)
+                       return ret;
        }
        mm->def_flags &= ~VM_MERGEABLE;
        return 0;
index 748456c365f4691af041753c63d6991f9bc8b4b8..9557c5a15b91e29a6465e502599960aad87e3e60 100644 (file)
@@ -29,9 +29,6 @@
 #define __PAGE_OFFSET __PAGE_OFFSET_BASE
 #include "../../mm/ident_map.c"
 
-/* Used by pgtable.h asm code to force instruction serialization. */
-unsigned long __force_order;
-
 /* Used to track our page table allocation area. */
 struct alloc_pgt_data {
        unsigned char *pgt_buf;
index ebe1685e92dda2bfd6795b45a92924de8a8f9451..d5e517d1c3ddc5c9ac6e594500d87524168b143d 100644 (file)
 #define MSR_K7_HWCR                    0xc0010015
 #define MSR_K7_HWCR_SMMLOCK_BIT                0
 #define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_HWCR_IRPERF_EN_BIT      30
+#define MSR_K7_HWCR_IRPERF_EN          BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
 #define MSR_K7_FID_VID_CTL             0xc0010041
 #define MSR_K7_FID_VID_STATUS          0xc0010042
 
index ac83a0fef6285d9901bf44b2b5169ab9fef89698..1f875fbe13846a9bfc00582173e6aedc571cd3ca 100644 (file)
@@ -28,6 +28,7 @@
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
+static const int amd_erratum_1054[];
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 /*
@@ -972,6 +973,15 @@ static void init_amd(struct cpuinfo_x86 *c)
        /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
        if (!cpu_has(c, X86_FEATURE_XENPV))
                set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+
+       /*
+        * Turn on the Instructions Retired free counter on machines not
+        * susceptible to erratum #1054 "Instructions Retired Performance
+        * Counter May Be Inaccurate".
+        */
+       if (cpu_has(c, X86_FEATURE_IRPERF) &&
+           !cpu_has_amd_erratum(c, amd_erratum_1054))
+               msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
 }
 
 #ifdef CONFIG_X86_32
@@ -1099,6 +1109,10 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+       AMD_OSVW_ERRATUM(0, AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
 
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
index b3a50d962851cec722df10623dbc90e6a3f16985..52de616a806559d6e0a25a5f65e3bef721432f48 100644 (file)
@@ -1163,9 +1163,12 @@ static const struct sysfs_ops threshold_ops = {
        .store                  = store,
 };
 
+static void threshold_block_release(struct kobject *kobj);
+
 static struct kobj_type threshold_ktype = {
        .sysfs_ops              = &threshold_ops,
        .default_attrs          = default_attrs,
+       .release                = threshold_block_release,
 };
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
@@ -1198,8 +1201,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
        return buf_mcatype;
 }
 
-static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
-                                    unsigned int block, u32 address)
+static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
+                                    unsigned int bank, unsigned int block,
+                                    u32 address)
 {
        struct threshold_block *b = NULL;
        u32 low, high;
@@ -1243,16 +1247,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
 
        INIT_LIST_HEAD(&b->miscj);
 
-       if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-               list_add(&b->miscj,
-                        &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-       } else {
-               per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-       }
+       if (tb->blocks)
+               list_add(&b->miscj, &tb->blocks->miscj);
+       else
+               tb->blocks = b;
 
-       err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-                                  per_cpu(threshold_banks, cpu)[bank]->kobj,
-                                  get_name(bank, b));
+       err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
        if (err)
                goto out_free;
 recurse:
@@ -1260,7 +1260,7 @@ recurse:
        if (!address)
                return 0;
 
-       err = allocate_threshold_blocks(cpu, bank, block, address);
+       err = allocate_threshold_blocks(cpu, tb, bank, block, address);
        if (err)
                goto out_free;
 
@@ -1345,8 +1345,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                goto out_free;
        }
 
-       per_cpu(threshold_banks, cpu)[bank] = b;
-
        if (is_shared_bank(bank)) {
                refcount_set(&b->cpus, 1);
 
@@ -1357,9 +1355,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                }
        }
 
-       err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
-       if (!err)
-               goto out;
+       err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
+       if (err)
+               goto out_free;
+
+       per_cpu(threshold_banks, cpu)[bank] = b;
+
+       return 0;
 
  out_free:
        kfree(b);
@@ -1368,8 +1370,12 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
        return err;
 }
 
-static void deallocate_threshold_block(unsigned int cpu,
-                                                unsigned int bank)
+static void threshold_block_release(struct kobject *kobj)
+{
+       kfree(to_block(kobj));
+}
+
+static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
 {
        struct threshold_block *pos = NULL;
        struct threshold_block *tmp = NULL;
@@ -1379,13 +1385,11 @@ static void deallocate_threshold_block(unsigned int cpu,
                return;
 
        list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-               kobject_put(&pos->kobj);
                list_del(&pos->miscj);
-               kfree(pos);
+               kobject_put(&pos->kobj);
        }
 
-       kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-       per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+       kobject_put(&head->blocks->kobj);
 }
 
 static void __threshold_remove_blocks(struct threshold_bank *b)
index 4d4f5d9faac314ad5fe5c21a05e72c873ec42d65..23054909c8ddfa4258fc9004877f6ceb88ef0786 100644 (file)
@@ -10,8 +10,6 @@ extern struct boot_params boot_params;
 
 static enum efi_secureboot_mode get_sb_mode(void)
 {
-       efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
-       efi_char16_t efi_SetupMode_name[] = L"SecureBoot";
        efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
        efi_status_t status;
        unsigned long size;
@@ -25,7 +23,7 @@ static enum efi_secureboot_mode get_sb_mode(void)
        }
 
        /* Get variable contents into buffer */
-       status = efi.get_variable(efi_SecureBoot_name, &efi_variable_guid,
+       status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
                                  NULL, &size, &secboot);
        if (status == EFI_NOT_FOUND) {
                pr_info("ima: secureboot mode disabled\n");
@@ -38,7 +36,7 @@ static enum efi_secureboot_mode get_sb_mode(void)
        }
 
        size = sizeof(setupmode);
-       status = efi.get_variable(efi_SetupMode_name, &efi_variable_guid,
+       status = efi.get_variable(L"SetupMode", &efi_variable_guid,
                                  NULL, &size, &setupmode);
 
        if (status != EFI_SUCCESS)      /* ignore unknown SetupMode */
index d817f255aed8e0b083bb04dfbce257c8c3b02a58..6efe0410fb728995ea8944ecd984840b6f30778e 100644 (file)
@@ -425,7 +425,29 @@ static void __init sev_map_percpu_data(void)
        }
 }
 
+static bool pv_tlb_flush_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+               kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
+static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
+
 #ifdef CONFIG_SMP
+
+static bool pv_ipi_supported(void)
+{
+       return kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI);
+}
+
+static bool pv_sched_yield_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
 #define KVM_IPI_CLUSTER_SIZE   (2 * BITS_PER_LONG)
 
 static void __send_ipi_mask(const struct cpumask *mask, int vector)
@@ -490,12 +512,12 @@ static void kvm_send_ipi_mask(const struct cpumask *mask, int vector)
 static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
 {
        unsigned int this_cpu = smp_processor_id();
-       struct cpumask new_mask;
+       struct cpumask *new_mask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
        const struct cpumask *local_mask;
 
-       cpumask_copy(&new_mask, mask);
-       cpumask_clear_cpu(this_cpu, &new_mask);
-       local_mask = &new_mask;
+       cpumask_copy(new_mask, mask);
+       cpumask_clear_cpu(this_cpu, new_mask);
+       local_mask = new_mask;
        __send_ipi_mask(local_mask, vector);
 }
 
@@ -575,7 +597,6 @@ static void __init kvm_apf_trap_init(void)
        update_intr_gate(X86_TRAP_PF, async_page_fault);
 }
 
-static DEFINE_PER_CPU(cpumask_var_t, __pv_tlb_mask);
 
 static void kvm_flush_tlb_others(const struct cpumask *cpumask,
                        const struct flush_tlb_info *info)
@@ -583,7 +604,7 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
        u8 state;
        int cpu;
        struct kvm_steal_time *src;
-       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_tlb_mask);
+       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
 
        cpumask_copy(flushmask, cpumask);
        /*
@@ -619,11 +640,10 @@ static void __init kvm_guest_init(void)
                pv_ops.time.steal_clock = kvm_steal_clock;
        }
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported()) {
                pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others;
                pv_ops.mmu.tlb_remove_table = tlb_remove_table;
+               pr_info("KVM setup pv remote TLB flush\n");
        }
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
@@ -632,9 +652,7 @@ static void __init kvm_guest_init(void)
 #ifdef CONFIG_SMP
        smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
        smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_sched_yield_supported()) {
                smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
                pr_info("KVM setup pv sched yield\n");
        }
@@ -700,7 +718,7 @@ static uint32_t __init kvm_detect(void)
 static void __init kvm_apic_init(void)
 {
 #if defined(CONFIG_SMP)
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI))
+       if (pv_ipi_supported())
                kvm_setup_pv_ipi();
 #endif
 }
@@ -732,26 +750,31 @@ static __init int activate_jump_labels(void)
 }
 arch_initcall(activate_jump_labels);
 
-static __init int kvm_setup_pv_tlb_flush(void)
+static __init int kvm_alloc_cpumask(void)
 {
        int cpu;
+       bool alloc = false;
 
        if (!kvm_para_available() || nopv)
                return 0;
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported())
+               alloc = true;
+
+#if defined(CONFIG_SMP)
+       if (pv_ipi_supported())
+               alloc = true;
+#endif
+
+       if (alloc)
                for_each_possible_cpu(cpu) {
-                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu),
+                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_cpu_mask, cpu),
                                GFP_KERNEL, cpu_to_node(cpu));
                }
-               pr_info("KVM setup pv remote TLB flush\n");
-       }
 
        return 0;
 }
-arch_initcall(kvm_setup_pv_tlb_flush);
+arch_initcall(kvm_alloc_cpumask);
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
 
index 991019d5eee1e03c21bd20a6e88ee209696304e0..1bb4927030afd85081a862544c7e29717fdc0fca 100644 (file)
@@ -59,6 +59,19 @@ config KVM
 
          If unsure, say N.
 
+config KVM_WERROR
+       bool "Compile KVM with -Werror"
+       # KASAN may cause the build to fail due to larger frames
+       default y if X86_64 && !KASAN
+       # We use the dependency on !COMPILE_TEST to not be enabled
+       # blindly in allmodconfig or allyesconfig configurations
+       depends on (X86_64 && !KASAN) || !COMPILE_TEST
+       depends on EXPERT
+       help
+         Add -Werror to the build flags for (and only for) i915.ko.
+
+         If in doubt, say "N".
+
 config KVM_INTEL
        tristate "KVM for Intel (and compatible) processors support"
        depends on KVM && IA32_FEAT_CTL
index 4654e97a05ccbe78e97b90b28ccd968419dcefb6..e553f0fdd87d47dbd0fe4dc5cb79f5e5421e0e64 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 ccflags-y += -Iarch/x86/kvm
-ccflags-y += -Werror
+ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
 KVM := ../../../virt/kvm
 
index 08280d8a2ac982131cc7975fdc933764a4f895c7..60ae93b09e72892d8d75f1149c37d8ffc8aeb950 100644 (file)
@@ -338,7 +338,7 @@ void kvm_set_cpu_caps(void)
        kvm_cpu_cap_mask(CPUID_7_EDX,
                F(AVX512_4VNNIW) | F(AVX512_4FMAPS) | F(SPEC_CTRL) |
                F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
-               F(MD_CLEAR)
+               F(MD_CLEAR) | F(AVX512_VP2INTERSECT) | F(FSRM)
        );
 
        /* TSC_ADJUST and ARCH_CAPABILITIES are emulated in software. */
@@ -990,13 +990,15 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
 {
        u32 orig_function = *eax, function = *eax, index = *ecx;
        struct kvm_cpuid_entry2 *entry;
-       bool exact;
+       bool exact, used_max_basic = false;
 
        entry = kvm_find_cpuid_entry(vcpu, function, index);
        exact = !!entry;
 
-       if (!entry && !exact_only)
+       if (!entry && !exact_only) {
                entry = get_out_of_range_cpuid_entry(vcpu, &function, index);
+               used_max_basic = !!entry;
+       }
 
        if (entry) {
                *eax = entry->eax;
@@ -1026,7 +1028,8 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
                        }
                }
        }
-       trace_kvm_cpuid(orig_function, *eax, *ebx, *ecx, *edx, exact);
+       trace_kvm_cpuid(orig_function, index, *eax, *ebx, *ecx, *edx, exact,
+                       used_max_basic);
        return exact;
 }
 EXPORT_SYMBOL_GPL(kvm_cpuid);
index 41bd49ebe3558392ae2b3235a131b4502bc67701..b754e49adbc598b50e9e3411dd95291b0fb7986f 100644 (file)
@@ -1241,7 +1241,7 @@ void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector)
 }
 EXPORT_SYMBOL_GPL(kvm_apic_set_eoi_accelerated);
 
-static void apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high)
+void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high)
 {
        struct kvm_lapic_irq irq;
 
@@ -1955,7 +1955,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
        case APIC_ICR:
                /* No delay here, so we always clear the pending bit */
                val &= ~(1 << 12);
-               apic_send_ipi(apic, val, kvm_lapic_get_reg(apic, APIC_ICR2));
+               kvm_apic_send_ipi(apic, val, kvm_lapic_get_reg(apic, APIC_ICR2));
                kvm_lapic_set_reg(apic, APIC_ICR, val);
                break;
 
index 7581bc2dcd4765cd61d8d6f5b1cb381d65f20411..40ed6ed22751086a530d5596f65dabbdbfca6bd1 100644 (file)
@@ -96,6 +96,7 @@ void kvm_apic_update_apicv(struct kvm_vcpu *vcpu);
 
 bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
                struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
+void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
 
 u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
 int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
index 08568ae9f7a183741998fa9798d8ef54459139e7..05cb45bc0e089756c20fc4075dc528ef5c566a03 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id svm_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_SVM),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
+#endif
 
 #define IOPM_ALLOC_ORDER 2
 #define MSRPM_ALLOC_ORDER 1
@@ -2230,8 +2232,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 static int avic_init_vcpu(struct vcpu_svm *svm)
 {
        int ret;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
 
-       if (!kvm_vcpu_apicv_active(&svm->vcpu))
+       if (!avic || !irqchip_in_kernel(vcpu->kvm))
                return 0;
 
        ret = avic_init_backing_page(&svm->vcpu);
@@ -3558,6 +3561,9 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
 
 static bool nested_vmcb_checks(struct vmcb *vmcb)
 {
+       if ((vmcb->save.efer & EFER_SVME) == 0)
+               return false;
+
        if ((vmcb->control.intercept & (1ULL << INTERCEPT_VMRUN)) == 0)
                return false;
 
index 6c4d9b4caf0704eb53fb1eda2c7d9c08d875d736..c3d1e9f4a2c00ac07efdfcfa505a43110ec8dc02 100644 (file)
@@ -151,32 +151,38 @@ TRACE_EVENT(kvm_fast_mmio,
  * Tracepoint for cpuid.
  */
 TRACE_EVENT(kvm_cpuid,
-       TP_PROTO(unsigned int function, unsigned long rax, unsigned long rbx,
-                unsigned long rcx, unsigned long rdx, bool found),
-       TP_ARGS(function, rax, rbx, rcx, rdx, found),
+       TP_PROTO(unsigned int function, unsigned int index, unsigned long rax,
+                unsigned long rbx, unsigned long rcx, unsigned long rdx,
+                bool found, bool used_max_basic),
+       TP_ARGS(function, index, rax, rbx, rcx, rdx, found, used_max_basic),
 
        TP_STRUCT__entry(
                __field(        unsigned int,   function        )
+               __field(        unsigned int,   index           )
                __field(        unsigned long,  rax             )
                __field(        unsigned long,  rbx             )
                __field(        unsigned long,  rcx             )
                __field(        unsigned long,  rdx             )
                __field(        bool,           found           )
+               __field(        bool,           used_max_basic  )
        ),
 
        TP_fast_assign(
                __entry->function       = function;
+               __entry->index          = index;
                __entry->rax            = rax;
                __entry->rbx            = rbx;
                __entry->rcx            = rcx;
                __entry->rdx            = rdx;
                __entry->found          = found;
+               __entry->used_max_basic = used_max_basic;
        ),
 
-       TP_printk("func %x rax %lx rbx %lx rcx %lx rdx %lx, cpuid entry %s",
-                 __entry->function, __entry->rax,
+       TP_printk("func %x idx %x rax %lx rbx %lx rcx %lx rdx %lx, cpuid entry %s%s",
+                 __entry->function, __entry->index, __entry->rax,
                  __entry->rbx, __entry->rcx, __entry->rdx,
-                 __entry->found ? "found" : "not found")
+                 __entry->found ? "found" : "not found",
+                 __entry->used_max_basic ? ", used max basic" : "")
 );
 
 #define AREG(x) { APIC_##x, "APIC_" #x }
index 8578513907d738616050da35b7f76e5547d242a0..4ff859c99946ea3ef0f4e3f791f5ac970f504022 100644 (file)
@@ -3527,7 +3527,7 @@ static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu,
 }
 
 
-static void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu)
+void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu)
 {
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        gfn_t gfn;
@@ -5543,8 +5543,7 @@ bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
-       if (vmx->nested.nested_run_pending)
-               return false;
+       WARN_ON_ONCE(vmx->nested.nested_run_pending);
 
        if (unlikely(vmx->fail)) {
                trace_kvm_nested_vmenter_failed(
@@ -5553,19 +5552,6 @@ bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
                return true;
        }
 
-       /*
-        * The host physical addresses of some pages of guest memory
-        * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
-        * Page). The CPU may write to these pages via their host
-        * physical address while L2 is running, bypassing any
-        * address-translation-based dirty tracking (e.g. EPT write
-        * protection).
-        *
-        * Mark them dirty on every exit from L2 to prevent them from
-        * getting out of sync with dirty tracking.
-        */
-       nested_mark_vmcs12_pages_dirty(vcpu);
-
        trace_kvm_nested_vmexit(kvm_rip_read(vcpu), exit_reason,
                                vmcs_readl(EXIT_QUALIFICATION),
                                vmx->idt_vectoring_info,
index 21d36652f213eec3f4601965561d5bfd1671a5e2..f70968b76d3318cdc5c62993fcb36c8ee459daa8 100644 (file)
@@ -33,6 +33,7 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
                        u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
 void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu);
+void nested_mark_vmcs12_pages_dirty(struct kvm_vcpu *vcpu);
 bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
                                 int size);
 
index 81ada2ce99e7c5a3ba7d66d04d0d982a78e8d5fe..ca2065166d1d4a358d4460d0252bb4c911106e29 100644 (file)
@@ -135,12 +135,12 @@ SYM_FUNC_START(__vmx_vcpu_run)
        cmpb $0, %bl
 
        /* Load guest registers.  Don't clobber flags. */
-       mov VCPU_RBX(%_ASM_AX), %_ASM_BX
        mov VCPU_RCX(%_ASM_AX), %_ASM_CX
        mov VCPU_RDX(%_ASM_AX), %_ASM_DX
+       mov VCPU_RBX(%_ASM_AX), %_ASM_BX
+       mov VCPU_RBP(%_ASM_AX), %_ASM_BP
        mov VCPU_RSI(%_ASM_AX), %_ASM_SI
        mov VCPU_RDI(%_ASM_AX), %_ASM_DI
-       mov VCPU_RBP(%_ASM_AX), %_ASM_BP
 #ifdef CONFIG_X86_64
        mov VCPU_R8 (%_ASM_AX),  %r8
        mov VCPU_R9 (%_ASM_AX),  %r9
@@ -168,12 +168,12 @@ SYM_FUNC_START(__vmx_vcpu_run)
 
        /* Save all guest registers, including RAX from the stack */
        __ASM_SIZE(pop) VCPU_RAX(%_ASM_AX)
-       mov %_ASM_BX,   VCPU_RBX(%_ASM_AX)
        mov %_ASM_CX,   VCPU_RCX(%_ASM_AX)
        mov %_ASM_DX,   VCPU_RDX(%_ASM_AX)
+       mov %_ASM_BX,   VCPU_RBX(%_ASM_AX)
+       mov %_ASM_BP,   VCPU_RBP(%_ASM_AX)
        mov %_ASM_SI,   VCPU_RSI(%_ASM_AX)
        mov %_ASM_DI,   VCPU_RDI(%_ASM_AX)
-       mov %_ASM_BP,   VCPU_RBP(%_ASM_AX)
 #ifdef CONFIG_X86_64
        mov %r8,  VCPU_R8 (%_ASM_AX)
        mov %r9,  VCPU_R9 (%_ASM_AX)
@@ -197,12 +197,12 @@ SYM_FUNC_START(__vmx_vcpu_run)
         * free.  RSP and RAX are exempt as RSP is restored by hardware during
         * VM-Exit and RAX is explicitly loaded with 0 or 1 to return VM-Fail.
         */
-1:     xor %ebx, %ebx
-       xor %ecx, %ecx
+1:     xor %ecx, %ecx
        xor %edx, %edx
+       xor %ebx, %ebx
+       xor %ebp, %ebp
        xor %esi, %esi
        xor %edi, %edi
-       xor %ebp, %ebp
 #ifdef CONFIG_X86_64
        xor %r8d,  %r8d
        xor %r9d,  %r9d
index b447d66f44e60d881e9d5610d459abb3c34fe998..a7dd67859bd48db9e8fd77e529157c223c796298 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id vmx_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_VMX),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
+#endif
 
 bool __read_mostly enable_vpid = 1;
 module_param_named(vpid, enable_vpid, bool, 0444);
@@ -653,53 +655,16 @@ static int vmx_set_guest_msr(struct vcpu_vmx *vmx, struct shared_msr_entry *msr,
        return ret;
 }
 
-void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)
-{
-       vmcs_clear(loaded_vmcs->vmcs);
-       if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
-               vmcs_clear(loaded_vmcs->shadow_vmcs);
-       loaded_vmcs->cpu = -1;
-       loaded_vmcs->launched = 0;
-}
-
 #ifdef CONFIG_KEXEC_CORE
-/*
- * This bitmap is used to indicate whether the vmclear
- * operation is enabled on all cpus. All disabled by
- * default.
- */
-static cpumask_t crash_vmclear_enabled_bitmap = CPU_MASK_NONE;
-
-static inline void crash_enable_local_vmclear(int cpu)
-{
-       cpumask_set_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
-static inline void crash_disable_local_vmclear(int cpu)
-{
-       cpumask_clear_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
-static inline int crash_local_vmclear_enabled(int cpu)
-{
-       return cpumask_test_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
 static void crash_vmclear_local_loaded_vmcss(void)
 {
        int cpu = raw_smp_processor_id();
        struct loaded_vmcs *v;
 
-       if (!crash_local_vmclear_enabled(cpu))
-               return;
-
        list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
                            loaded_vmcss_on_cpu_link)
                vmcs_clear(v->vmcs);
 }
-#else
-static inline void crash_enable_local_vmclear(int cpu) { }
-static inline void crash_disable_local_vmclear(int cpu) { }
 #endif /* CONFIG_KEXEC_CORE */
 
 static void __loaded_vmcs_clear(void *arg)
@@ -711,19 +676,24 @@ static void __loaded_vmcs_clear(void *arg)
                return; /* vcpu migration can race with cpu offline */
        if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
                per_cpu(current_vmcs, cpu) = NULL;
-       crash_disable_local_vmclear(cpu);
+
+       vmcs_clear(loaded_vmcs->vmcs);
+       if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
+               vmcs_clear(loaded_vmcs->shadow_vmcs);
+
        list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
 
        /*
-        * we should ensure updating loaded_vmcs->loaded_vmcss_on_cpu_link
-        * is before setting loaded_vmcs->vcpu to -1 which is done in
-        * loaded_vmcs_init. Otherwise, other cpu can see vcpu = -1 fist
-        * then adds the vmcs into percpu list before it is deleted.
+        * Ensure all writes to loaded_vmcs, including deleting it from its
+        * current percpu list, complete before setting loaded_vmcs->vcpu to
+        * -1, otherwise a different cpu can see vcpu == -1 first and add
+        * loaded_vmcs to its percpu list before it's deleted from this cpu's
+        * list. Pairs with the smp_rmb() in vmx_vcpu_load_vmcs().
         */
        smp_wmb();
 
-       loaded_vmcs_init(loaded_vmcs);
-       crash_enable_local_vmclear(cpu);
+       loaded_vmcs->cpu = -1;
+       loaded_vmcs->launched = 0;
 }
 
 void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
@@ -1342,18 +1312,17 @@ void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu)
        if (!already_loaded) {
                loaded_vmcs_clear(vmx->loaded_vmcs);
                local_irq_disable();
-               crash_disable_local_vmclear(cpu);
 
                /*
-                * Read loaded_vmcs->cpu should be before fetching
-                * loaded_vmcs->loaded_vmcss_on_cpu_link.
-                * See the comments in __loaded_vmcs_clear().
+                * Ensure loaded_vmcs->cpu is read before adding loaded_vmcs to
+                * this cpu's percpu list, otherwise it may not yet be deleted
+                * from its previous cpu's percpu list.  Pairs with the
+                * smb_wmb() in __loaded_vmcs_clear().
                 */
                smp_rmb();
 
                list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
                         &per_cpu(loaded_vmcss_on_cpu, cpu));
-               crash_enable_local_vmclear(cpu);
                local_irq_enable();
        }
 
@@ -2251,18 +2220,33 @@ static __init int vmx_disabled_by_bios(void)
               !boot_cpu_has(X86_FEATURE_VMX);
 }
 
-static void kvm_cpu_vmxon(u64 addr)
+static int kvm_cpu_vmxon(u64 vmxon_pointer)
 {
+       u64 msr;
+
        cr4_set_bits(X86_CR4_VMXE);
        intel_pt_handle_vmx(1);
 
-       asm volatile ("vmxon %0" : : "m"(addr));
+       asm_volatile_goto("1: vmxon %[vmxon_pointer]\n\t"
+                         _ASM_EXTABLE(1b, %l[fault])
+                         : : [vmxon_pointer] "m"(vmxon_pointer)
+                         : : fault);
+       return 0;
+
+fault:
+       WARN_ONCE(1, "VMXON faulted, MSR_IA32_FEAT_CTL (0x3a) = 0x%llx\n",
+                 rdmsrl_safe(MSR_IA32_FEAT_CTL, &msr) ? 0xdeadbeef : msr);
+       intel_pt_handle_vmx(0);
+       cr4_clear_bits(X86_CR4_VMXE);
+
+       return -EFAULT;
 }
 
 static int hardware_enable(void)
 {
        int cpu = raw_smp_processor_id();
        u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
+       int r;
 
        if (cr4_read_shadow() & X86_CR4_VMXE)
                return -EBUSY;
@@ -2279,18 +2263,10 @@ static int hardware_enable(void)
        INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
        spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
 
-       /*
-        * Now we can enable the vmclear operation in kdump
-        * since the loaded_vmcss_on_cpu list on this cpu
-        * has been initialized.
-        *
-        * Though the cpu is not in VMX operation now, there
-        * is no problem to enable the vmclear operation
-        * for the loaded_vmcss_on_cpu list is empty!
-        */
-       crash_enable_local_vmclear(cpu);
+       r = kvm_cpu_vmxon(phys_addr);
+       if (r)
+               return r;
 
-       kvm_cpu_vmxon(phys_addr);
        if (enable_ept)
                ept_sync_global();
 
@@ -2590,9 +2566,12 @@ int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
        if (!loaded_vmcs->vmcs)
                return -ENOMEM;
 
+       vmcs_clear(loaded_vmcs->vmcs);
+
        loaded_vmcs->shadow_vmcs = NULL;
        loaded_vmcs->hv_timer_soft_disabled = false;
-       loaded_vmcs_init(loaded_vmcs);
+       loaded_vmcs->cpu = -1;
+       loaded_vmcs->launched = 0;
 
        if (cpu_has_vmx_msr_bitmap()) {
                loaded_vmcs->msr_bitmap = (unsigned long *)
@@ -5851,8 +5830,23 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu,
        if (vmx->emulation_required)
                return handle_invalid_guest_state(vcpu);
 
-       if (is_guest_mode(vcpu) && nested_vmx_exit_reflected(vcpu, exit_reason))
-               return nested_vmx_reflect_vmexit(vcpu, exit_reason);
+       if (is_guest_mode(vcpu)) {
+               /*
+                * The host physical addresses of some pages of guest memory
+                * are loaded into the vmcs02 (e.g. vmcs12's Virtual APIC
+                * Page). The CPU may write to these pages via their host
+                * physical address while L2 is running, bypassing any
+                * address-translation-based dirty tracking (e.g. EPT write
+                * protection).
+                *
+                * Mark them dirty on every exit from L2 to prevent them from
+                * getting out of sync with dirty tracking.
+                */
+               nested_mark_vmcs12_pages_dirty(vcpu);
+
+               if (nested_vmx_exit_reflected(vcpu, exit_reason))
+                       return nested_vmx_reflect_vmexit(vcpu, exit_reason);
+       }
 
        if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
                dump_vmcs();
@@ -7171,6 +7165,7 @@ static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
        else
                intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
 
+       /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
        return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
 }
 
@@ -7200,6 +7195,20 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        case x86_intercept_outs:
                return vmx_check_intercept_io(vcpu, info);
 
+       case x86_intercept_lgdt:
+       case x86_intercept_lidt:
+       case x86_intercept_lldt:
+       case x86_intercept_ltr:
+       case x86_intercept_sgdt:
+       case x86_intercept_sidt:
+       case x86_intercept_sldt:
+       case x86_intercept_str:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
+                       return X86EMUL_CONTINUE;
+
+               /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+               break;
+
        /* TODO: check more intercepts... */
        default:
                break;
index be93d597306cf691c4e0158c7bf09b98f7ec98ee..79d38f41ef7a191ac77a90f1880494c3943e6f79 100644 (file)
@@ -492,7 +492,6 @@ struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags);
 void free_vmcs(struct vmcs *vmcs);
 int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs);
 void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs);
-void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs);
 void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs);
 
 static inline struct vmcs *alloc_vmcs(bool shadow)
index e54c6ad628a810a047e1754f8196f2ec5e11ec42..1b6d9ac9533c9bb430c932ec0a5b9f53a3137166 100644 (file)
@@ -1585,8 +1585,12 @@ static int handle_fastpath_set_x2apic_icr_irqoff(struct kvm_vcpu *vcpu, u64 data
                ((data & APIC_DEST_MASK) == APIC_DEST_PHYSICAL) &&
                ((data & APIC_MODE_MASK) == APIC_DM_FIXED)) {
 
+               data &= ~(1 << 12);
+               kvm_apic_send_ipi(vcpu->arch.apic, (u32)data, (u32)(data >> 32));
                kvm_lapic_set_reg(vcpu->arch.apic, APIC_ICR2, (u32)(data >> 32));
-               return kvm_lapic_reg_write(vcpu->arch.apic, APIC_ICR, (u32)data);
+               kvm_lapic_set_reg(vcpu->arch.apic, APIC_ICR, (u32)data);
+               trace_kvm_apic_write(APIC_ICR, (u32)data);
+               return 0;
        }
 
        return 1;
@@ -1595,11 +1599,12 @@ static int handle_fastpath_set_x2apic_icr_irqoff(struct kvm_vcpu *vcpu, u64 data
 enum exit_fastpath_completion handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu)
 {
        u32 msr = kvm_rcx_read(vcpu);
-       u64 data = kvm_read_edx_eax(vcpu);
+       u64 data;
        int ret = 0;
 
        switch (msr) {
        case APIC_BASE_MSR + (APIC_ICR >> 4):
+               data = kvm_read_edx_eax(vcpu);
                ret = handle_fastpath_set_x2apic_icr_irqoff(vcpu, data);
                break;
        default:
@@ -3488,7 +3493,7 @@ long kvm_arch_dev_ioctl(struct file *filp,
                r = 0;
                break;
        }
-       case KVM_X86_GET_MCE_CAP_SUPPORTED: {
+       case KVM_X86_GET_MCE_CAP_SUPPORTED:
                r = -EFAULT;
                if (copy_to_user(argp, &kvm_mce_cap_supported,
                                 sizeof(kvm_mce_cap_supported)))
@@ -3520,9 +3525,9 @@ long kvm_arch_dev_ioctl(struct file *filp,
        case KVM_GET_MSRS:
                r = msr_io(NULL, argp, do_get_msr_feature, 1);
                break;
-       }
        default:
                r = -EINVAL;
+               break;
        }
 out:
        return r;
@@ -7190,15 +7195,15 @@ static void kvm_timer_init(void)
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
 #ifdef CONFIG_CPU_FREQ
-               struct cpufreq_policy policy;
+               struct cpufreq_policy *policy;
                int cpu;
 
-               memset(&policy, 0, sizeof(policy));
                cpu = get_cpu();
-               cpufreq_get_policy(&policy, cpu);
-               if (policy.cpuinfo.max_freq)
-                       max_tsc_khz = policy.cpuinfo.max_freq;
+               policy = cpufreq_cpu_get(cpu);
+               if (policy && policy->cpuinfo.max_freq)
+                       max_tsc_khz = policy->cpuinfo.max_freq;
                put_cpu();
+               cpufreq_cpu_put(policy);
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -7308,12 +7313,12 @@ int kvm_arch_init(void *opaque)
        }
 
        if (!ops->cpu_has_kvm_support()) {
-               printk(KERN_ERR "kvm: no hardware support\n");
+               pr_err_ratelimited("kvm: no hardware support\n");
                r = -EOPNOTSUPP;
                goto out;
        }
        if (ops->disabled_by_bios()) {
-               printk(KERN_ERR "kvm: disabled by bios\n");
+               pr_err_ratelimited("kvm: disabled by bios\n");
                r = -EOPNOTSUPP;
                goto out;
        }
index 1f756ffffe8b3159dade936c5eecda8d847900b8..79409120a6036c6852894b54509e3662ce5d3f6f 100644 (file)
@@ -896,14 +896,15 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
+#ifdef CONFIG_X86_64
+       unsigned int which;
+       u64 base;
+#endif
 
        ret = 0;
 
        switch (msr) {
 #ifdef CONFIG_X86_64
-               unsigned which;
-               u64 base;
-
        case MSR_FS_BASE:               which = SEGBASE_FS; goto set;
        case MSR_KERNEL_GS_BASE:        which = SEGBASE_GS_USER; goto set;
        case MSR_GS_BASE:               which = SEGBASE_GS_KERNEL; goto set;
index 3f977c517960e61dca951551d437b52abcacd588..5cc775bdb06acbfac9dbfa79551d97f28c5a97cb 100644 (file)
@@ -412,7 +412,7 @@ void blk_insert_flush(struct request *rq)
         */
        if ((policy & REQ_FSEQ_DATA) &&
            !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
-               blk_mq_request_bypass_insert(rq, false);
+               blk_mq_request_bypass_insert(rq, false, false);
                return;
        }
 
index ca22afd47b3dcce1ea72da7f4a6218c4ac9d85b5..856356b1619e83f05fc86fc37ed4a9086b413d86 100644 (file)
@@ -361,13 +361,19 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
                                       bool has_sched,
                                       struct request *rq)
 {
-       /* dispatch flush rq directly */
-       if (rq->rq_flags & RQF_FLUSH_SEQ) {
-               spin_lock(&hctx->lock);
-               list_add(&rq->queuelist, &hctx->dispatch);
-               spin_unlock(&hctx->lock);
+       /*
+        * dispatch flush and passthrough rq directly
+        *
+        * passthrough request has to be added to hctx->dispatch directly.
+        * For some reason, device may be in one situation which can't
+        * handle FS request, so STS_RESOURCE is always returned and the
+        * FS request will be added to hctx->dispatch. However passthrough
+        * request may be required at that time for fixing the problem. If
+        * passthrough request is added to scheduler queue, there isn't any
+        * chance to dispatch it given we prioritize requests in hctx->dispatch.
+        */
+       if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
                return true;
-       }
 
        if (has_sched)
                rq->rq_flags |= RQF_SORTED;
@@ -391,8 +397,10 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head,
 
        WARN_ON(e && (rq->tag != -1));
 
-       if (blk_mq_sched_bypass_insert(hctx, !!e, rq))
+       if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
+               blk_mq_request_bypass_insert(rq, at_head, false);
                goto run;
+       }
 
        if (e && e->type->ops.insert_requests) {
                LIST_HEAD(list);
index fbacde454718583555b38f07d0fe88ad89b712c3..586c9d6e904ab8aade50bea050a5a973bb2a273e 100644 (file)
@@ -183,8 +183,8 @@ found_tag:
        return tag + tag_offset;
 }
 
-void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags,
-                   struct blk_mq_ctx *ctx, unsigned int tag)
+void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
+                   unsigned int tag)
 {
        if (!blk_mq_tag_is_reserved(tags, tag)) {
                const int real_tag = tag - tags->nr_reserved_tags;
index 15bc74acb57eca1c56bf0564cb000c002ea08618..2b8321efb68206cce7a865e801bf5d980629a487 100644 (file)
@@ -26,8 +26,8 @@ extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, unsigned int r
 extern void blk_mq_free_tags(struct blk_mq_tags *tags);
 
 extern unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data);
-extern void blk_mq_put_tag(struct blk_mq_hw_ctx *hctx, struct blk_mq_tags *tags,
-                          struct blk_mq_ctx *ctx, unsigned int tag);
+extern void blk_mq_put_tag(struct blk_mq_tags *tags, struct blk_mq_ctx *ctx,
+                          unsigned int tag);
 extern int blk_mq_tag_update_depth(struct blk_mq_hw_ctx *hctx,
                                        struct blk_mq_tags **tags,
                                        unsigned int depth, bool can_grow);
index a12b1763508d3194853b6d33a057a62da62ea0e0..d92088dec6c359afd83642af362372b651b3d7e9 100644 (file)
@@ -477,9 +477,9 @@ static void __blk_mq_free_request(struct request *rq)
        blk_pm_mark_last_busy(rq);
        rq->mq_hctx = NULL;
        if (rq->tag != -1)
-               blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag);
+               blk_mq_put_tag(hctx->tags, ctx, rq->tag);
        if (sched_tag != -1)
-               blk_mq_put_tag(hctx, hctx->sched_tags, ctx, sched_tag);
+               blk_mq_put_tag(hctx->sched_tags, ctx, sched_tag);
        blk_mq_sched_restart(hctx);
        blk_queue_exit(q);
 }
@@ -735,7 +735,7 @@ static void blk_mq_requeue_work(struct work_struct *work)
                 * merge.
                 */
                if (rq->rq_flags & RQF_DONTPREP)
-                       blk_mq_request_bypass_insert(rq, false);
+                       blk_mq_request_bypass_insert(rq, false, false);
                else
                        blk_mq_sched_insert_request(rq, true, false, false);
        }
@@ -1286,7 +1286,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
                        q->mq_ops->commit_rqs(hctx);
 
                spin_lock(&hctx->lock);
-               list_splice_init(list, &hctx->dispatch);
+               list_splice_tail_init(list, &hctx->dispatch);
                spin_unlock(&hctx->lock);
 
                /*
@@ -1677,12 +1677,16 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
  * Should only be used carefully, when the caller knows we want to
  * bypass a potential IO scheduler on the target device.
  */
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue)
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+                                 bool run_queue)
 {
        struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 
        spin_lock(&hctx->lock);
-       list_add_tail(&rq->queuelist, &hctx->dispatch);
+       if (at_head)
+               list_add(&rq->queuelist, &hctx->dispatch);
+       else
+               list_add_tail(&rq->queuelist, &hctx->dispatch);
        spin_unlock(&hctx->lock);
 
        if (run_queue)
@@ -1849,7 +1853,7 @@ insert:
        if (bypass_insert)
                return BLK_STS_RESOURCE;
 
-       blk_mq_request_bypass_insert(rq, run_queue);
+       blk_mq_request_bypass_insert(rq, false, run_queue);
        return BLK_STS_OK;
 }
 
@@ -1876,7 +1880,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
 
        ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true);
        if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
-               blk_mq_request_bypass_insert(rq, true);
+               blk_mq_request_bypass_insert(rq, false, true);
        else if (ret != BLK_STS_OK)
                blk_mq_end_request(rq, ret);
 
@@ -1910,7 +1914,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                if (ret != BLK_STS_OK) {
                        if (ret == BLK_STS_RESOURCE ||
                                        ret == BLK_STS_DEV_RESOURCE) {
-                               blk_mq_request_bypass_insert(rq,
+                               blk_mq_request_bypass_insert(rq, false,
                                                        list_empty(list));
                                break;
                        }
@@ -3398,7 +3402,6 @@ static void blk_mq_poll_stats_fn(struct blk_stat_callback *cb)
 }
 
 static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
-                                      struct blk_mq_hw_ctx *hctx,
                                       struct request *rq)
 {
        unsigned long ret = 0;
@@ -3431,7 +3434,6 @@ static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
 }
 
 static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
-                                    struct blk_mq_hw_ctx *hctx,
                                     struct request *rq)
 {
        struct hrtimer_sleeper hs;
@@ -3451,7 +3453,7 @@ static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
        if (q->poll_nsec > 0)
                nsecs = q->poll_nsec;
        else
-               nsecs = blk_mq_poll_nsecs(q, hctx, rq);
+               nsecs = blk_mq_poll_nsecs(q, rq);
 
        if (!nsecs)
                return false;
@@ -3506,7 +3508,7 @@ static bool blk_mq_poll_hybrid(struct request_queue *q,
                        return false;
        }
 
-       return blk_mq_poll_hybrid_sleep(q, hctx, rq);
+       return blk_mq_poll_hybrid_sleep(q, rq);
 }
 
 /**
index eaaca8fc1c2874e77e9fce95964444ddaf280745..10bfdfb494faf4035f8be143f1cf6e47e32fe50c 100644 (file)
@@ -66,7 +66,8 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
  */
 void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
                                bool at_head);
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue);
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+                                 bool run_queue);
 void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
                                struct list_head *list);
 
@@ -199,7 +200,7 @@ static inline bool blk_mq_get_dispatch_budget(struct blk_mq_hw_ctx *hctx)
 static inline void __blk_mq_put_driver_tag(struct blk_mq_hw_ctx *hctx,
                                           struct request *rq)
 {
-       blk_mq_put_tag(hctx, hctx->tags, rq->mq_ctx, rq->tag);
+       blk_mq_put_tag(hctx->tags, rq->mq_ctx, rq->tag);
        rq->tag = -1;
 
        if (rq->rq_flags & RQF_MQ_INFLIGHT) {
index c754cb75dd1a96a5f52b39ed17adc6be45347345..a49ff96bde7784f9095ac7ecab8ff65124b7b17c 100644 (file)
@@ -26,7 +26,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
        [HASH_ALGO_TGR_128]     = "tgr128",
        [HASH_ALGO_TGR_160]     = "tgr160",
        [HASH_ALGO_TGR_192]     = "tgr192",
-       [HASH_ALGO_SM3_256]     = "sm3-256",
+       [HASH_ALGO_SM3_256]     = "sm3",
        [HASH_ALGO_STREEBOG_256] = "streebog256",
        [HASH_ALGO_STREEBOG_512] = "streebog512",
 };
index b5516b04ffc07b95a5869678f0886499fa9553bc..6e9ec6e3fe47d63ea9adf07e540ac2a223379a06 100644 (file)
@@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
 }
 #endif
 
+static bool acpi_no_watchdog;
+
 static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
 {
        const struct acpi_table_wdat *wdat = NULL;
        acpi_status status;
 
-       if (acpi_disabled)
+       if (acpi_disabled || acpi_no_watchdog)
                return NULL;
 
        status = acpi_get_table(ACPI_SIG_WDAT, 0,
@@ -88,6 +90,14 @@ bool acpi_has_watchdog(void)
 }
 EXPORT_SYMBOL_GPL(acpi_has_watchdog);
 
+/* ACPI watchdog can be disabled on boot command line */
+static int __init disable_acpi_watchdog(char *str)
+{
+       acpi_no_watchdog = true;
+       return 1;
+}
+__setup("acpi_no_watchdog", disable_acpi_watchdog);
+
 void __init acpi_watchdog_init(void)
 {
        const struct acpi_wdat_entry *entries;
@@ -126,12 +136,11 @@ void __init acpi_watchdog_init(void)
                gas = &entries[i].register_region;
 
                res.start = gas->address;
+               res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
                if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
                        res.flags = IORESOURCE_MEM;
-                       res.end = res.start + ALIGN(gas->access_width, 4) - 1;
                } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
                        res.flags = IORESOURCE_IO;
-                       res.end = res.start + gas->access_width - 1;
                } else {
                        pr_warn("Unsupported address space: %u\n",
                                gas->space_id);
index 8c83d8c620dc3deb10dc9a5a61b75bd6b2b0251b..789d5e920aaf7084058512e09467b554a9b5120d 100644 (file)
@@ -265,4 +265,49 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
                 handler) (acpi_gbl_fixed_event_handlers[event].context));
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_any_fixed_event_status_set
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      TRUE or FALSE
+ *
+ * DESCRIPTION: Checks the PM status register for active fixed events
+ *
+ ******************************************************************************/
+
+u32 acpi_any_fixed_event_status_set(void)
+{
+       acpi_status status;
+       u32 in_status;
+       u32 in_enable;
+       u32 i;
+
+       status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
+       if (ACPI_FAILURE(status)) {
+               return (FALSE);
+       }
+
+       status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
+       if (ACPI_FAILURE(status)) {
+               return (FALSE);
+       }
+
+       /*
+        * Check for all possible Fixed Events and dispatch those that are active
+        */
+       for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+
+               /* Both the status and enable bits must be on for this event */
+
+               if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
+                   (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
+                       return (TRUE);
+               }
+       }
+
+       return (FALSE);
+}
+
 #endif                         /* !ACPI_REDUCED_HARDWARE */
index 152f7fc0b2003f1fcfc89105a7547df358e51ee9..e5f95922bc217e42342cce186bf0968c7e7f31dd 100644 (file)
@@ -1005,6 +1005,13 @@ static bool acpi_s2idle_wake(void)
                if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
                        return true;
 
+               /*
+                * If the status bit of any enabled fixed event is set, the
+                * wakeup is regarded as valid.
+                */
+               if (acpi_any_fixed_event_status_set())
+                       return true;
+
                /*
                 * If there are no EC events to process and at least one of the
                 * other enabled GPEs is active, the wakeup is regarded as a
index cd3612e4e2e14317ca506e24f00c4f9a6a2f9a73..8ef65c0856407cfbf780e370bf24a5141d8938f5 100644 (file)
@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+       unsigned int new_fdc = fdc;
+
        if (drive >= 0 && drive < N_DRIVE) {
-               fdc = FDC(drive);
+               new_fdc = FDC(drive);
                current_drive = drive;
        }
-       if (fdc != 1 && fdc != 0) {
+       if (new_fdc >= N_FDC) {
                pr_info("bad fdc value\n");
                return;
        }
+       fdc = new_fdc;
        set_dor(fdc, ~0, 8);
 #if N_FDC > 1
        set_dor(1 - fdc, ~8, 0);
index bc837862b7679ac88b0e8ef15d33e61f388114f5..62b660821dbcc19b390712b4088fc7141a4b27c2 100644 (file)
@@ -14,9 +14,6 @@
 #include <linux/fault-inject.h>
 
 struct nullb_cmd {
-       struct list_head list;
-       struct llist_node ll_list;
-       struct __call_single_data csd;
        struct request *rq;
        struct bio *bio;
        unsigned int tag;
index 16510795e37720de6b4c233bbd9c0f4bcf798e05..133060431dbdb2f2c058876c75072571c9141c41 100644 (file)
@@ -1518,8 +1518,6 @@ static int setup_commands(struct nullb_queue *nq)
 
        for (i = 0; i < nq->queue_depth; i++) {
                cmd = &nq->cmds[i];
-               INIT_LIST_HEAD(&cmd->list);
-               cmd->ll_list.next = NULL;
                cmd->tag = -1U;
        }
 
index 117cfc8cd05a4c509876d137bf7fb3e2bd272382..cda5cf917e9afaee700470b00e26d8aaeb7fffef 100644 (file)
@@ -276,7 +276,7 @@ static const struct block_device_operations pcd_bdops = {
        .release        = pcd_block_release,
        .ioctl          = pcd_block_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl          = blkdev_compat_ptr_ioctl,
+       .compat_ioctl   = blkdev_compat_ptr_ioctl,
 #endif
        .check_events   = pcd_block_check_events,
 };
index 886b2638c730308a6dce2061b18a06b04845fa18..c51292c2a131e0133872258e11470b6c5c58b73a 100644 (file)
@@ -519,7 +519,7 @@ static const struct block_device_operations gdrom_bdops = {
        .check_events           = gdrom_bdops_check_events,
        .ioctl                  = gdrom_bdops_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl                  = blkdev_compat_ptr_ioctl,
+       .compat_ioctl           = blkdev_compat_ptr_ioctl,
 #endif
 };
 
index 5a0d99d4fec0b1870e9f7b63e5e9e4444aa6950c..9567e5197f740f3c3b3ffeadc0495c928cd94399 100644 (file)
@@ -21,9 +21,11 @@ tpm-$(CONFIG_EFI) += eventlog/efi.o
 tpm-$(CONFIG_OF) += eventlog/of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
-obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi_mod.o
-tpm_tis_spi_mod-y := tpm_tis_spi.o
-tpm_tis_spi_mod-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
+
+obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
+tpm_tis_spi-y := tpm_tis_spi_main.o
+tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
+
 obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
 obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
 obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
index 13696deceae8e7fb73862ea99d731a58fe647f67..760329598b9960855f42119ed01098acca312057 100644 (file)
@@ -525,6 +525,8 @@ static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index)
                return 0;
        }
 
+       bank->crypto_id = HASH_ALGO__LAST;
+
        return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size);
 }
 
index cbe6c94bf158648ac0240037b5aac0fac8f38422..808874bccf4ace34791e520b8d5bde8854d1dbb4 100644 (file)
@@ -1076,9 +1076,17 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
                        pol = policy->last_policy;
                } else if (def_gov) {
                        pol = cpufreq_parse_policy(def_gov->name);
-               } else {
-                       return -ENODATA;
+                       /*
+                        * In case the default governor is neiter "performance"
+                        * nor "powersave", fall back to the initial policy
+                        * value set by the driver.
+                        */
+                       if (pol == CPUFREQ_POLICY_UNKNOWN)
+                               pol = policy->policy;
                }
+               if (pol != CPUFREQ_POLICY_PERFORMANCE &&
+                   pol != CPUFREQ_POLICY_POWERSAVE)
+                       return -ENODATA;
        }
 
        return cpufreq_set_policy(policy, gov, pol);
index cceee8bc3c2f745a02ab7b648d29458cbeaf2283..7dcf2093e5316a229dd9396feb73011a3f4f5fe3 100644 (file)
@@ -738,7 +738,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
 {
        struct devfreq *devfreq;
        struct devfreq_governor *governor;
-       static atomic_t devfreq_no = ATOMIC_INIT(-1);
        int err = 0;
 
        if (!dev || !profile || !governor_name) {
@@ -800,8 +799,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
        atomic_set(&devfreq->suspend_count, 0);
 
-       dev_set_name(&devfreq->dev, "devfreq%d",
-                               atomic_inc_return(&devfreq_no));
+       dev_set_name(&devfreq->dev, "%s", dev_name(dev));
        err = device_register(&devfreq->dev);
        if (err) {
                mutex_unlock(&devfreq->lock);
index 92ce6d85802cc0602146bd23f6a276245f9d2db1..4cc0e630ab79b0be31ff97962a6a9c45507399f7 100644 (file)
@@ -55,6 +55,7 @@ config FSI_MASTER_AST_CF
 
 config FSI_MASTER_ASPEED
        tristate "FSI ASPEED master"
+       depends on HAS_IOMEM
        help
         This option enables a FSI master that is present behind an OPB bridge
         in the AST2600.
index 94e2fd758e0130ab0185820e1905917e68c439d0..42f4febe24c6db0d5642b23acd9aa46dd9ab8db5 100644 (file)
@@ -1389,7 +1389,7 @@ amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_ATOMIC |
+           DRIVER_ATOMIC |
            DRIVER_GEM |
            DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
            DRIVER_SYNCOBJ_TIMELINE,
index d3c27a3c43f68ad5ed11ff5b0379d8d06c648d13..7546da0cc70c7019c94f58fb0ee66debcdc93a22 100644 (file)
@@ -195,6 +195,7 @@ struct amdgpu_gmc {
        uint32_t                srbm_soft_reset;
        bool                    prt_warning;
        uint64_t                stolen_size;
+       uint32_t                sdpif_register;
        /* apertures */
        u64                     shared_aperture_start;
        u64                     shared_aperture_end;
index 3a1570dafe3482ac93992c0e76e1777d185721d6..146f96661b6b5c8945ba985bc047e1ccbd71fe38 100644 (file)
@@ -1013,6 +1013,30 @@ static int psp_dtm_initialize(struct psp_context *psp)
        return 0;
 }
 
+static int psp_dtm_unload(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the unloading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
 int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
 {
        /*
@@ -1037,7 +1061,7 @@ static int psp_dtm_terminate(struct psp_context *psp)
        if (!psp->dtm_context.dtm_initialized)
                return 0;
 
-       ret = psp_hdcp_unload(psp);
+       ret = psp_dtm_unload(psp);
        if (ret)
                return ret;
 
index 1785fdad6ecbaa4631468e7202470708465c3d9c..22bbb36c768e2bbe5b49f4c0187368d223717559 100644 (file)
@@ -3923,11 +3923,13 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
 
+       amdgpu_gfx_off_ctrl(adev, false);
        mutex_lock(&adev->gfx.gpu_clock_mutex);
        WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
        clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
                ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
+       amdgpu_gfx_off_ctrl(adev, true);
        return clock;
 }
 
index b33a4eb39193c55fa32989116f7da788bb0cb37e..3afdbbd6aaad9254d0fa9ead8a10ebf74f023ec2 100644 (file)
@@ -1193,6 +1193,14 @@ static bool gfx_v9_0_should_disable_gfxoff(struct pci_dev *pdev)
        return false;
 }
 
+static bool is_raven_kicker(struct amdgpu_device *adev)
+{
+       if (adev->pm.fw_version >= 0x41e2b)
+               return true;
+       else
+               return false;
+}
+
 static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
 {
        if (gfx_v9_0_should_disable_gfxoff(adev->pdev))
@@ -1205,9 +1213,8 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
                break;
        case CHIP_RAVEN:
                if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8) &&
-                   ((adev->gfx.rlc_fw_version != 106 &&
+                   ((!is_raven_kicker(adev) &&
                      adev->gfx.rlc_fw_version < 531) ||
-                    (adev->gfx.rlc_fw_version == 53815) ||
                     (adev->gfx.rlc_feature_version < 1) ||
                     !adev->gfx.rlc.is_rlc_v2_1))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
@@ -3959,6 +3966,7 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
 
+       amdgpu_gfx_off_ctrl(adev, false);
        mutex_lock(&adev->gfx.gpu_clock_mutex);
        if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) {
                uint32_t tmp, lsb, msb, i = 0;
@@ -3977,6 +3985,7 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
                        ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
        }
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
+       amdgpu_gfx_off_ctrl(adev, true);
        return clock;
 }
 
index 90216abf14a4c356732a7950284d835f19fbc9de..cc0c273a86f9298b19e60dbf4e401d9fe440017e 100644 (file)
@@ -1271,6 +1271,19 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+/**
+ * gmc_v9_0_restore_registers - restores regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This restores register values, saved at suspend.
+ */
+static void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
+}
+
 /**
  * gmc_v9_0_gart_enable - gart enable
  *
@@ -1376,6 +1389,20 @@ static int gmc_v9_0_hw_init(void *handle)
        return r;
 }
 
+/**
+ * gmc_v9_0_save_registers - saves regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This saves potential register values that should be
+ * restored upon resume
+ */
+static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
+}
+
 /**
  * gmc_v9_0_gart_disable - gart disable
  *
@@ -1412,9 +1439,16 @@ static int gmc_v9_0_hw_fini(void *handle)
 
 static int gmc_v9_0_suspend(void *handle)
 {
+       int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       return gmc_v9_0_hw_fini(adev);
+       r = gmc_v9_0_hw_fini(adev);
+       if (r)
+               return r;
+
+       gmc_v9_0_save_registers(adev);
+
+       return 0;
 }
 
 static int gmc_v9_0_resume(void *handle)
@@ -1422,6 +1456,7 @@ static int gmc_v9_0_resume(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       gmc_v9_0_restore_registers(adev);
        r = gmc_v9_0_hw_init(adev);
        if (r)
                return r;
index 15f3424a1ff792b299f83c71c335461f08177d10..2b488dfb2f21cfe192b733ab70da9b41d8d05d03 100644 (file)
@@ -272,7 +272,12 @@ static u32 soc15_get_config_memsize(struct amdgpu_device *adev)
 
 static u32 soc15_get_xclk(struct amdgpu_device *adev)
 {
-       return adev->clock.spll.reference_freq;
+       u32 reference_clock = adev->clock.spll.reference_freq;
+
+       if (adev->asic_type == CHIP_RAVEN)
+               return reference_clock / 4;
+
+       return reference_clock;
 }
 
 
index 63e8a12a74bcb5581ec949a630e7885c3a56615d..e8f66fbf399e54c130bfe61a3148a7bc254839fc 100644 (file)
@@ -1911,7 +1911,7 @@ static void handle_hpd_irq(void *param)
        mutex_lock(&aconnector->hpd_lock);
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       if (adev->asic_type >= CHIP_RAVEN)
+       if (adev->dm.hdcp_workqueue)
                hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
 #endif
        if (aconnector->fake_enable)
@@ -2088,8 +2088,10 @@ static void handle_hpd_rx_irq(void *param)
                }
        }
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ)
-               hdcp_handle_cpirq(adev->dm.hdcp_workqueue,  aconnector->base.index);
+           if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
+                   if (adev->dm.hdcp_workqueue)
+                           hdcp_handle_cpirq(adev->dm.hdcp_workqueue,  aconnector->base.index);
+           }
 #endif
        if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
            (dc_link->type == dc_connection_mst_branch))
@@ -5702,7 +5704,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-               if (adev->asic_type >= CHIP_RAVEN)
+               if (adev->dm.hdcp_workqueue)
                        drm_connector_attach_content_protection_property(&aconnector->base, true);
 #endif
        }
index f730b94ac3c0633d584524296a1ca403028990b8..55246711700ba721f4ce02141fde6c1dae6cdefd 100644 (file)
@@ -46,8 +46,8 @@ static inline enum mod_hdcp_status check_hdcp2_capable(struct mod_hdcp *hdcp)
        enum mod_hdcp_status status;
 
        if (is_dp_hdcp(hdcp))
-               status = (hdcp->auth.msg.hdcp2.rxcaps_dp[2] & HDCP_2_2_RX_CAPS_VERSION_VAL) &&
-                               HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[0]) ?
+               status = (hdcp->auth.msg.hdcp2.rxcaps_dp[0] == HDCP_2_2_RX_CAPS_VERSION_VAL) &&
+                               HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[2]) ?
                                MOD_HDCP_STATUS_SUCCESS :
                                MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
        else
index b6f74bf4af023fd53ee79ce44ecb29cf9f8cb43b..27bb8c1ab85876bed4ad23bfc6df7648eaa8a851 100644 (file)
 #define mmCRTC4_CRTC_DRR_CONTROL                                                                       0x0f3e
 #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX                                                              2
 
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0                                                                  0x395d
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX                                                         2
 
 // addressBlock: dce_dc_fmt4_dispdec
 // base address: 0x2000
index 0dc49479a7ebdabe0650d06b29db032c91843845..c9e5ce135fd42bd417fa64b1fe43bed8fee6cf45 100644 (file)
@@ -898,6 +898,9 @@ int smu_v11_0_system_features_control(struct smu_context *smu,
        if (ret)
                return ret;
 
+       bitmap_zero(feature->enabled, feature->feature_num);
+       bitmap_zero(feature->supported, feature->feature_num);
+
        if (en) {
                ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
                if (ret)
@@ -907,9 +910,6 @@ int smu_v11_0_system_features_control(struct smu_context *smu,
                            feature->feature_num);
                bitmap_copy(feature->supported, (unsigned long *)&feature_mask,
                            feature->feature_num);
-       } else {
-               bitmap_zero(feature->enabled, feature->feature_num);
-               bitmap_zero(feature->supported, feature->feature_num);
        }
 
        return ret;
@@ -978,8 +978,12 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
        struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
        int ret = 0;
 
-       max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
+       if (!smu->smu_table.max_sustainable_clocks)
+               max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
                                         GFP_KERNEL);
+       else
+               max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
+
        smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
 
        max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
index 3709e5ace7246086b3b4d172bdd5a7218cbf6306..fbdb42d4e772ecf87666fe28191559f06afd8cf1 100644 (file)
@@ -297,7 +297,7 @@ static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr,
 
 static int tc_aux_wait_busy(struct tc_data *tc)
 {
-       return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 1000, 100000);
+       return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 100, 100000);
 }
 
 static int tc_aux_write_data(struct tc_data *tc, const void *data,
@@ -640,7 +640,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
        if (ret)
                goto err;
 
-       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 100, 100000);
        if (ret == -ETIMEDOUT) {
                dev_err(tc->dev, "Timeout waiting for PHY to become ready");
                return ret;
@@ -876,7 +876,7 @@ static int tc_wait_link_training(struct tc_data *tc)
        int ret;
 
        ret = tc_poll_timeout(tc, DP0_LTSTAT, LT_LOOPDONE,
-                             LT_LOOPDONE, 1, 1000);
+                             LT_LOOPDONE, 500, 100000);
        if (ret) {
                dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n");
                return ret;
@@ -949,7 +949,7 @@ static int tc_main_link_enable(struct tc_data *tc)
        dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST);
        ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
 
-       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 500, 100000);
        if (ret) {
                dev_err(dev, "timeout waiting for phy become ready");
                return ret;
index 6f6d6d1e60ae9162d94c45e8e4e58cc6d389448b..f195a4732e0badac04f0864def9999bd1620b575 100644 (file)
@@ -140,7 +140,8 @@ static int tfp410_attach(struct drm_bridge *bridge)
                                          dvi->connector_type,
                                          dvi->ddc);
        if (ret) {
-               dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
+               dev_err(dvi->dev, "drm_connector_init_with_ddc() failed: %d\n",
+                       ret);
                return ret;
        }
 
index 6d4a29e99ae264ea55985be4594a08319a53d6f1..3035584f6dc724ec81a5f7a7ffafc82745b043c6 100644 (file)
@@ -951,7 +951,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
         * depending on the hardware this may require the framebuffer
         * to be in a specific tiling format.
         */
-       if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
+       if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
+            (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
            !plane->rotation_property)
                return false;
 
index 10336b144c722b5aa03bca91d3d28685c009bf72..d4d64518e11b8fc06f45eddf2673a8c6ba0bfe34 100644 (file)
@@ -1698,6 +1698,13 @@ static int drm_mode_parse_cmdline_options(const char *str,
        if (rotation && freestanding)
                return -EINVAL;
 
+       if (!(rotation & DRM_MODE_ROTATE_MASK))
+               rotation |= DRM_MODE_ROTATE_0;
+
+       /* Make sure there is exactly one rotation defined */
+       if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
+               return -EINVAL;
+
        mode->rotation_reflection = rotation;
 
        return 0;
index ba9595960bbebf290170a2bfb6247320a5fb8a21..907c4471f5916d742c4d65610374b80657fa74c9 100644 (file)
@@ -75,9 +75,8 @@ config DRM_I915_CAPTURE_ERROR
        help
          This option enables capturing the GPU state when a hang is detected.
          This information is vital for triaging hangs and assists in debugging.
-         Please report any hang to
-           https://bugs.freedesktop.org/enter_bug.cgi?product=DRI
-         for triaging.
+         Please report any hang for triaging according to:
+           https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 
          If in doubt, say "Y".
 
index b8c5f8934dbdf61792997b1cb6b03650a6dca6bf..a1f2411aa21b26a034b27312077d5f3764bb9083 100644 (file)
@@ -294,7 +294,7 @@ extra-$(CONFIG_DRM_I915_WERROR) += \
                $(shell cd $(srctree)/$(src) && find * -name '*.h')))
 
 quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
-      cmd_hdrtest = $(CC) $(c_flags) -S -o /dev/null -x c /dev/null -include $<; touch $@
+      cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@
 
 $(obj)/%.hdrtest: $(src)/%.h FORCE
        $(call if_changed_dep,hdrtest)
index 33f1dc3d7c1a6d896054a83bc32a200689395527..d9a61f341070bd3df7fd1fddc0d68abf911fe526 100644 (file)
@@ -4251,7 +4251,9 @@ static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
 void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
                                         struct intel_crtc_state *crtc_state)
 {
-       if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
+       if (IS_ELKHARTLAKE(dev_priv) && crtc_state->port_clock > 594000)
+               crtc_state->min_voltage_level = 3;
+       else if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 1;
        else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 2;
index 064dd99bbc4992912bfd1688b80b4dd901aff9cd..aa453953908b54ff27fe2d2d60a12639b4d31fc0 100644 (file)
@@ -11087,7 +11087,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
        u32 base;
 
        if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
-               base = obj->phys_handle->busaddr;
+               base = sg_dma_address(obj->mm.pages->sgl);
        else
                base = intel_plane_ggtt_offset(plane_state);
 
@@ -17433,6 +17433,24 @@ retry:
                         * have readout for pipe gamma enable.
                         */
                        crtc_state->uapi.color_mgmt_changed = true;
+
+                       /*
+                        * FIXME hack to force full modeset when DSC is being
+                        * used.
+                        *
+                        * As long as we do not have full state readout and
+                        * config comparison of crtc_state->dsc, we have no way
+                        * to ensure reliable fastset. Remove once we have
+                        * readout for DSC.
+                        */
+                       if (crtc_state->dsc.compression_enable) {
+                               ret = drm_atomic_add_affected_connectors(state,
+                                                                        &crtc->base);
+                               if (ret)
+                                       goto out;
+                               crtc_state->uapi.mode_changed = true;
+                               drm_dbg_kms(dev, "Force full modeset for DSC\n");
+                       }
                }
        }
 
index a2e57e62af30adc05e562ca734f3891ceda33fe2..151a1e8ae36abbc7cafea3c9aa9c4b7cb88014c4 100644 (file)
@@ -565,6 +565,22 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state)
                if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))
                        return -ENODEV;
 
+               /*
+                * If the cancel fails, we then need to reset, cleanly!
+                *
+                * If the per-engine reset fails, all hope is lost! We resort
+                * to a full GPU reset in that unlikely case, but realistically
+                * if the engine could not reset, the full reset does not fare
+                * much better. The damage has been done.
+                *
+                * However, if we cannot reset an engine by itself, we cannot
+                * cleanup a hanging persistent context without causing
+                * colateral damage, and we should not pretend we can by
+                * exposing the interface.
+                */
+               if (!intel_has_reset_engine(&ctx->i915->gt))
+                       return -ENODEV;
+
                i915_gem_context_clear_persistence(ctx);
        }
 
index f64ad77e6b1ee4f665dcb1cf69c8600fa94f51a6..c2174da35bb0fdf3890af589440be127676df876 100644 (file)
@@ -285,9 +285,6 @@ struct drm_i915_gem_object {
 
                void *gvt_info;
        };
-
-       /** for phys allocated objects */
-       struct drm_dma_handle *phys_handle;
 };
 
 static inline struct drm_i915_gem_object *
index b1b7c1b3038aaa41b8bbdc1c5c7cdfef13d4e2d0..b07bb40edd5a3d8ad83fe9ed0d2b93b96f6c9ecd 100644 (file)
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
        struct address_space *mapping = obj->base.filp->f_mapping;
-       struct drm_dma_handle *phys;
-       struct sg_table *st;
        struct scatterlist *sg;
-       char *vaddr;
+       struct sg_table *st;
+       dma_addr_t dma;
+       void *vaddr;
+       void *dst;
        int i;
-       int err;
 
        if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
                return -EINVAL;
 
-       /* Always aligning to the object size, allows a single allocation
+       /*
+        * Always aligning to the object size, allows a single allocation
         * to handle all possible callers, and given typical object sizes,
         * the alignment of the buddy allocation will naturally match.
         */
-       phys = drm_pci_alloc(obj->base.dev,
-                            roundup_pow_of_two(obj->base.size),
-                            roundup_pow_of_two(obj->base.size));
-       if (!phys)
+       vaddr = dma_alloc_coherent(&obj->base.dev->pdev->dev,
+                                  roundup_pow_of_two(obj->base.size),
+                                  &dma, GFP_KERNEL);
+       if (!vaddr)
                return -ENOMEM;
 
-       vaddr = phys->vaddr;
+       st = kmalloc(sizeof(*st), GFP_KERNEL);
+       if (!st)
+               goto err_pci;
+
+       if (sg_alloc_table(st, 1, GFP_KERNEL))
+               goto err_st;
+
+       sg = st->sgl;
+       sg->offset = 0;
+       sg->length = obj->base.size;
+
+       sg_assign_page(sg, (struct page *)vaddr);
+       sg_dma_address(sg) = dma;
+       sg_dma_len(sg) = obj->base.size;
+
+       dst = vaddr;
        for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
                struct page *page;
-               char *src;
+               void *src;
 
                page = shmem_read_mapping_page(mapping, i);
-               if (IS_ERR(page)) {
-                       err = PTR_ERR(page);
-                       goto err_phys;
-               }
+               if (IS_ERR(page))
+                       goto err_st;
 
                src = kmap_atomic(page);
-               memcpy(vaddr, src, PAGE_SIZE);
-               drm_clflush_virt_range(vaddr, PAGE_SIZE);
+               memcpy(dst, src, PAGE_SIZE);
+               drm_clflush_virt_range(dst, PAGE_SIZE);
                kunmap_atomic(src);
 
                put_page(page);
-               vaddr += PAGE_SIZE;
+               dst += PAGE_SIZE;
        }
 
        intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-       st = kmalloc(sizeof(*st), GFP_KERNEL);
-       if (!st) {
-               err = -ENOMEM;
-               goto err_phys;
-       }
-
-       if (sg_alloc_table(st, 1, GFP_KERNEL)) {
-               kfree(st);
-               err = -ENOMEM;
-               goto err_phys;
-       }
-
-       sg = st->sgl;
-       sg->offset = 0;
-       sg->length = obj->base.size;
-
-       sg_dma_address(sg) = phys->busaddr;
-       sg_dma_len(sg) = obj->base.size;
-
-       obj->phys_handle = phys;
-
        __i915_gem_object_set_pages(obj, st, sg->length);
 
        return 0;
 
-err_phys:
-       drm_pci_free(obj->base.dev, phys);
-
-       return err;
+err_st:
+       kfree(st);
+err_pci:
+       dma_free_coherent(&obj->base.dev->pdev->dev,
+                         roundup_pow_of_two(obj->base.size),
+                         vaddr, dma);
+       return -ENOMEM;
 }
 
 static void
 i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                               struct sg_table *pages)
 {
+       dma_addr_t dma = sg_dma_address(pages->sgl);
+       void *vaddr = sg_page(pages->sgl);
+
        __i915_gem_object_release_shmem(obj, pages, false);
 
        if (obj->mm.dirty) {
                struct address_space *mapping = obj->base.filp->f_mapping;
-               char *vaddr = obj->phys_handle->vaddr;
+               void *src = vaddr;
                int i;
 
                for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
@@ -115,15 +114,16 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                                continue;
 
                        dst = kmap_atomic(page);
-                       drm_clflush_virt_range(vaddr, PAGE_SIZE);
-                       memcpy(dst, vaddr, PAGE_SIZE);
+                       drm_clflush_virt_range(src, PAGE_SIZE);
+                       memcpy(dst, src, PAGE_SIZE);
                        kunmap_atomic(dst);
 
                        set_page_dirty(page);
                        if (obj->mm.madv == I915_MADV_WILLNEED)
                                mark_page_accessed(page);
                        put_page(page);
-                       vaddr += PAGE_SIZE;
+
+                       src += PAGE_SIZE;
                }
                obj->mm.dirty = false;
        }
@@ -131,7 +131,9 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
        sg_free_table(pages);
        kfree(pages);
 
-       drm_pci_free(obj->base.dev, obj->phys_handle);
+       dma_free_coherent(&obj->base.dev->pdev->dev,
+                         roundup_pow_of_two(obj->base.size),
+                         vaddr, dma);
 }
 
 static void phys_release(struct drm_i915_gem_object *obj)
index f7e4b39c734f36e76d79d0ae2c250d709fb7ba8d..59b387ade49c079a1c605cb8754a617186ed3407 100644 (file)
@@ -256,8 +256,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
        with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
                freed = i915_gem_shrink(i915, -1UL, NULL,
                                        I915_SHRINK_BOUND |
-                                       I915_SHRINK_UNBOUND |
-                                       I915_SHRINK_ACTIVE);
+                                       I915_SHRINK_UNBOUND);
        }
 
        return freed;
@@ -336,7 +335,6 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
        freed_pages = 0;
        with_intel_runtime_pm(&i915->runtime_pm, wakeref)
                freed_pages += i915_gem_shrink(i915, -1UL, NULL,
-                                              I915_SHRINK_ACTIVE |
                                               I915_SHRINK_BOUND |
                                               I915_SHRINK_UNBOUND |
                                               I915_SHRINK_WRITEBACK);
index 0ba524a414c68d66558afe24674613a2229451ee..cbad7fe722cebb840f50c46ad73f9f1c63c49c78 100644 (file)
@@ -136,6 +136,9 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl)
        struct intel_engine_cs *engine =
                container_of(b, struct intel_engine_cs, breadcrumbs);
 
+       if (unlikely(intel_engine_is_virtual(engine)))
+               engine = intel_virtual_engine_get_sibling(engine, 0);
+
        intel_engine_add_retire(engine, tl);
 }
 
index 7ef1d37970f6d4942d3ec2d1028f2e4d9467a8f1..8a5054f21bf880644a0bc3002971bf63491406ff 100644 (file)
@@ -99,6 +99,9 @@ static bool add_retire(struct intel_engine_cs *engine,
 void intel_engine_add_retire(struct intel_engine_cs *engine,
                             struct intel_timeline *tl)
 {
+       /* We don't deal well with the engine disappearing beneath us */
+       GEM_BUG_ON(intel_engine_is_virtual(engine));
+
        if (add_retire(engine, tl))
                schedule_work(&engine->retire_work);
 }
index a13a8c4b65ab94a5f4f8c7e48ed2af5c0683e57f..fe8a59aaa629a1bf8d01367c796307234302bdac 100644 (file)
@@ -237,7 +237,8 @@ static void execlists_init_reg_state(u32 *reg_state,
                                     bool close);
 static void
 __execlists_update_reg_state(const struct intel_context *ce,
-                            const struct intel_engine_cs *engine);
+                            const struct intel_engine_cs *engine,
+                            u32 head);
 
 static void mark_eio(struct i915_request *rq)
 {
@@ -1186,12 +1187,11 @@ static void reset_active(struct i915_request *rq,
                head = rq->tail;
        else
                head = active_request(ce->timeline, rq)->head;
-       ce->ring->head = intel_ring_wrap(ce->ring, head);
-       intel_ring_update_space(ce->ring);
+       head = intel_ring_wrap(ce->ring, head);
 
        /* Scrub the context image to prevent replaying the previous batch */
        restore_default_state(ce, engine);
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
 
        /* We've switched away, so this should be a no-op, but intent matters */
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
@@ -1321,7 +1321,7 @@ static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->context;
        u64 desc = ce->lrc_desc;
-       u32 tail;
+       u32 tail, prev;
 
        /*
         * WaIdleLiteRestore:bdw,skl
@@ -1334,9 +1334,15 @@ static u64 execlists_update_context(struct i915_request *rq)
         * subsequent resubmissions (for lite restore). Should that fail us,
         * and we try and submit the same tail again, force the context
         * reload.
+        *
+        * If we need to return to a preempted context, we need to skip the
+        * lite-restore and force it to reload the RING_TAIL. Otherwise, the
+        * HW has a tendency to ignore us rewinding the TAIL to the end of
+        * an earlier request.
         */
        tail = intel_ring_set_tail(rq->ring, rq->tail);
-       if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
+       prev = ce->lrc_reg_state[CTX_RING_TAIL];
+       if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
                desc |= CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state[CTX_RING_TAIL] = tail;
        rq->tail = rq->wa_tail;
@@ -1605,6 +1611,11 @@ last_active(const struct intel_engine_execlists *execlists)
        return *last;
 }
 
+#define for_each_waiter(p__, rq__) \
+       list_for_each_entry_lockless(p__, \
+                                    &(rq__)->sched.waiters_list, \
+                                    wait_link)
+
 static void defer_request(struct i915_request *rq, struct list_head * const pl)
 {
        LIST_HEAD(list);
@@ -1622,7 +1633,7 @@ static void defer_request(struct i915_request *rq, struct list_head * const pl)
                GEM_BUG_ON(i915_request_is_active(rq));
                list_move_tail(&rq->sched.link, pl);
 
-               list_for_each_entry(p, &rq->sched.waiters_list, wait_link) {
+               for_each_waiter(p, rq) {
                        struct i915_request *w =
                                container_of(p->waiter, typeof(*w), sched);
 
@@ -1834,14 +1845,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                         */
                        __unwind_incomplete_requests(engine);
 
-                       /*
-                        * If we need to return to the preempted context, we
-                        * need to skip the lite-restore and force it to
-                        * reload the RING_TAIL. Otherwise, the HW has a
-                        * tendency to ignore us rewinding the TAIL to the
-                        * end of an earlier request.
-                        */
-                       last->context->lrc_desc |= CTX_DESC_FORCE_RESTORE;
                        last = NULL;
                } else if (need_timeslice(engine, last) &&
                           timer_expired(&engine->execlists.timer)) {
@@ -2860,16 +2863,17 @@ static void execlists_context_unpin(struct intel_context *ce)
 
 static void
 __execlists_update_reg_state(const struct intel_context *ce,
-                            const struct intel_engine_cs *engine)
+                            const struct intel_engine_cs *engine,
+                            u32 head)
 {
        struct intel_ring *ring = ce->ring;
        u32 *regs = ce->lrc_reg_state;
 
-       GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head));
+       GEM_BUG_ON(!intel_ring_offset_valid(ring, head));
        GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
 
        regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
-       regs[CTX_RING_HEAD] = ring->head;
+       regs[CTX_RING_HEAD] = head;
        regs[CTX_RING_TAIL] = ring->tail;
 
        /* RPCS */
@@ -2898,7 +2902,7 @@ __execlists_context_pin(struct intel_context *ce,
 
        ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, ce->ring->tail);
 
        return 0;
 }
@@ -2939,7 +2943,7 @@ static void execlists_context_reset(struct intel_context *ce)
        /* Scrub away the garbage */
        execlists_init_reg_state(ce->lrc_reg_state,
                                 ce, ce->engine, ce->ring, true);
-       __execlists_update_reg_state(ce, ce->engine);
+       __execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
 
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
 }
@@ -3494,6 +3498,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
        struct intel_engine_execlists * const execlists = &engine->execlists;
        struct intel_context *ce;
        struct i915_request *rq;
+       u32 head;
 
        mb(); /* paranoia: read the CSB pointers from after the reset */
        clflush(execlists->csb_write);
@@ -3521,15 +3526,15 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
 
        if (i915_request_completed(rq)) {
                /* Idle context; tidy up the ring so we can restart afresh */
-               ce->ring->head = intel_ring_wrap(ce->ring, rq->tail);
+               head = intel_ring_wrap(ce->ring, rq->tail);
                goto out_replay;
        }
 
        /* Context has requests still in-flight; it should not be idle! */
        GEM_BUG_ON(i915_active_is_idle(&ce->active));
        rq = active_request(ce->timeline, rq);
-       ce->ring->head = intel_ring_wrap(ce->ring, rq->head);
-       GEM_BUG_ON(ce->ring->head == ce->ring->tail);
+       head = intel_ring_wrap(ce->ring, rq->head);
+       GEM_BUG_ON(head == ce->ring->tail);
 
        /*
         * If this request hasn't started yet, e.g. it is waiting on a
@@ -3574,10 +3579,9 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
 
 out_replay:
        ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n",
-                    ce->ring->head, ce->ring->tail);
-       intel_ring_update_space(ce->ring);
+                    head, ce->ring->tail);
        __execlists_reset_reg_state(ce, engine);
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
 
 unwind:
@@ -5220,10 +5224,7 @@ void intel_lr_context_reset(struct intel_engine_cs *engine,
                restore_default_state(ce, engine);
 
        /* Rerun the request; its payload has been neutered (if guilty). */
-       ce->ring->head = head;
-       intel_ring_update_space(ce->ring);
-
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
 }
 
 bool
index 374b28f13ca0b4565adc32cd621ce0d69ad81d2c..6ff803f397c4d7015b6bfdb84785f5c6b355b0ea 100644 (file)
@@ -145,6 +145,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
 
        kref_init(&ring->ref);
        ring->size = size;
+       ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
 
        /*
         * Workaround an erratum on the i830 which causes a hang if
index ea2839d9e044546957ea19133139c025375d9055..5bdce24994aa04ef80306a43e180c3599d81ee7c 100644 (file)
@@ -56,6 +56,14 @@ static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos)
        return pos & (ring->size - 1);
 }
 
+static inline int intel_ring_direction(const struct intel_ring *ring,
+                                      u32 next, u32 prev)
+{
+       typecheck(typeof(ring->size), next);
+       typecheck(typeof(ring->size), prev);
+       return (next - prev) << ring->wrap;
+}
+
 static inline bool
 intel_ring_offset_valid(const struct intel_ring *ring,
                        unsigned int pos)
index d9f17f38e0cce9e2a05adf2fe7a1efc00b3c7709..1a189ea00fd8240bbdf4fcdd45822f7e6240d787 100644 (file)
@@ -39,12 +39,13 @@ struct intel_ring {
         */
        atomic_t pin_count;
 
-       u32 head;
-       u32 tail;
-       u32 emit;
+       u32 head; /* updated during retire, loosely tracks RING_HEAD */
+       u32 tail; /* updated on submission, used for RING_TAIL */
+       u32 emit; /* updated during request construction */
 
        u32 space;
        u32 size;
+       u32 wrap;
        u32 effective_size;
 };
 
index 65718ca2326e82af7a847515318f02e88356d3ed..b292f8cbd0bf15eaa8a2f47b8b159069b852c40a 100644 (file)
@@ -186,7 +186,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                }
                GEM_BUG_ON(!ce[1]->ring->size);
                intel_ring_reset(ce[1]->ring, ce[1]->ring->size / 2);
-               __execlists_update_reg_state(ce[1], engine);
+               __execlists_update_reg_state(ce[1], engine, ce[1]->ring->head);
 
                rq[0] = igt_spinner_create_request(&spin, ce[0], MI_ARB_CHECK);
                if (IS_ERR(rq[0])) {
index 2477a1e5a1669cf220ccb85b062885714c100d3d..ae139f0877aeb72a098657ea296f876f6b8194a0 100644 (file)
@@ -151,12 +151,12 @@ static void dmabuf_gem_object_free(struct kref *kref)
                        dmabuf_obj = container_of(pos,
                                        struct intel_vgpu_dmabuf_obj, list);
                        if (dmabuf_obj == obj) {
+                               list_del(pos);
                                intel_gvt_hypervisor_put_vfio_device(vgpu);
                                idr_remove(&vgpu->object_idr,
                                           dmabuf_obj->dmabuf_id);
                                kfree(dmabuf_obj->info);
                                kfree(dmabuf_obj);
-                               list_del(pos);
                                break;
                        }
                }
index 85bd9bf4f6eee58b3c00e567a7c5286a017dccb9..487af6ea9972c44855fb1259935869ee541f2458 100644 (file)
@@ -560,9 +560,9 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
 
                intel_vgpu_reset_mmio(vgpu, dmlr);
                populate_pvinfo_page(vgpu);
-               intel_vgpu_reset_display(vgpu);
 
                if (dmlr) {
+                       intel_vgpu_reset_display(vgpu);
                        intel_vgpu_reset_cfg_space(vgpu);
                        /* only reset the failsafe mode when dmlr reset */
                        vgpu->failsafe = false;
index c2de2f45b459b85e428b2e11f7984a417158ae5f..5f6e639528219378a7a1346c8b14ce7df9bf2da6 100644 (file)
@@ -180,7 +180,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
                     struct drm_i915_gem_pwrite *args,
                     struct drm_file *file)
 {
-       void *vaddr = obj->phys_handle->vaddr + args->offset;
+       void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
        char __user *user_data = u64_to_user_ptr(args->data_ptr);
 
        /*
@@ -844,10 +844,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                ret = i915_gem_gtt_pwrite_fast(obj, args);
 
        if (ret == -EFAULT || ret == -ENOSPC) {
-               if (obj->phys_handle)
-                       ret = i915_gem_phys_pwrite(obj, args, file);
-               else
+               if (i915_gem_object_has_struct_page(obj))
                        ret = i915_gem_shmem_pwrite(obj, args);
+               else
+                       ret = i915_gem_phys_pwrite(obj, args, file);
        }
 
        i915_gem_object_unpin_pages(obj);
index 594341e27a47d1ee82a89d5971ad3e9566f9f273..9e401a5fcae8c9e64f7c244d71df6a261de83e21 100644 (file)
@@ -1852,7 +1852,8 @@ void i915_error_state_store(struct i915_gpu_coredump *error)
        if (!xchg(&warned, true) &&
            ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
                pr_info("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
-               pr_info("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
+               pr_info("Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/intel/issues/new.\n");
+               pr_info("Please see https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs for details.\n");
                pr_info("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
                pr_info("The GPU crash dump is required to analyze GPU hangs, so please always attach it.\n");
                pr_info("GPU crash dump saved to /sys/class/drm/card%d/error\n",
index 83f01401b8b5c5758dea58f7c8ed5dcf6c22c21c..f631f6d2112746d408af0945e4eedad3e03a037b 100644 (file)
@@ -437,7 +437,7 @@ static const struct intel_device_info snb_m_gt2_info = {
        .has_rc6 = 1, \
        .has_rc6p = 1, \
        .has_rps = true, \
-       .ppgtt_type = INTEL_PPGTT_FULL, \
+       .ppgtt_type = INTEL_PPGTT_ALIASING, \
        .ppgtt_size = 31, \
        IVB_PIPE_OFFSETS, \
        IVB_CURSOR_OFFSETS, \
@@ -494,7 +494,7 @@ static const struct intel_device_info vlv_info = {
        .has_rps = true,
        .display.has_gmch = 1,
        .display.has_hotplug = 1,
-       .ppgtt_type = INTEL_PPGTT_FULL,
+       .ppgtt_type = INTEL_PPGTT_ALIASING,
        .ppgtt_size = 31,
        .has_snoop = true,
        .has_coherent_ggtt = false,
index ec0299490dd4215b272ce986fd397ad4ddef01c6..aa729d04abe2ecba8b74b10600a850d020dfbcd6 100644 (file)
@@ -822,11 +822,6 @@ static ssize_t i915_pmu_event_show(struct device *dev,
        return sprintf(buf, "config=0x%lx\n", eattr->val);
 }
 
-static struct attribute_group i915_pmu_events_attr_group = {
-       .name = "events",
-       /* Patch in attrs at runtime. */
-};
-
 static ssize_t
 i915_pmu_get_attr_cpumask(struct device *dev,
                          struct device_attribute *attr,
@@ -846,13 +841,6 @@ static const struct attribute_group i915_pmu_cpumask_attr_group = {
        .attrs = i915_cpumask_attrs,
 };
 
-static const struct attribute_group *i915_pmu_attr_groups[] = {
-       &i915_pmu_format_attr_group,
-       &i915_pmu_events_attr_group,
-       &i915_pmu_cpumask_attr_group,
-       NULL
-};
-
 #define __event(__config, __name, __unit) \
 { \
        .config = (__config), \
@@ -1026,23 +1014,23 @@ err_alloc:
 
 static void free_event_attributes(struct i915_pmu *pmu)
 {
-       struct attribute **attr_iter = i915_pmu_events_attr_group.attrs;
+       struct attribute **attr_iter = pmu->events_attr_group.attrs;
 
        for (; *attr_iter; attr_iter++)
                kfree((*attr_iter)->name);
 
-       kfree(i915_pmu_events_attr_group.attrs);
+       kfree(pmu->events_attr_group.attrs);
        kfree(pmu->i915_attr);
        kfree(pmu->pmu_attr);
 
-       i915_pmu_events_attr_group.attrs = NULL;
+       pmu->events_attr_group.attrs = NULL;
        pmu->i915_attr = NULL;
        pmu->pmu_attr = NULL;
 }
 
 static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 {
-       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
+       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
 
        GEM_BUG_ON(!pmu->base.event_init);
 
@@ -1055,7 +1043,7 @@ static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 
 static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
 {
-       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
+       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
        unsigned int target;
 
        GEM_BUG_ON(!pmu->base.event_init);
@@ -1072,8 +1060,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
        return 0;
 }
 
-static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
-
 static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
 {
        enum cpuhp_state slot;
@@ -1087,21 +1073,22 @@ static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
                return ret;
 
        slot = ret;
-       ret = cpuhp_state_add_instance(slot, &pmu->node);
+       ret = cpuhp_state_add_instance(slot, &pmu->cpuhp.node);
        if (ret) {
                cpuhp_remove_multi_state(slot);
                return ret;
        }
 
-       cpuhp_slot = slot;
+       pmu->cpuhp.slot = slot;
        return 0;
 }
 
 static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
 {
-       WARN_ON(cpuhp_slot == CPUHP_INVALID);
-       WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &pmu->node));
-       cpuhp_remove_multi_state(cpuhp_slot);
+       WARN_ON(pmu->cpuhp.slot == CPUHP_INVALID);
+       WARN_ON(cpuhp_state_remove_instance(pmu->cpuhp.slot, &pmu->cpuhp.node));
+       cpuhp_remove_multi_state(pmu->cpuhp.slot);
+       pmu->cpuhp.slot = CPUHP_INVALID;
 }
 
 static bool is_igp(struct drm_i915_private *i915)
@@ -1118,6 +1105,13 @@ static bool is_igp(struct drm_i915_private *i915)
 void i915_pmu_register(struct drm_i915_private *i915)
 {
        struct i915_pmu *pmu = &i915->pmu;
+       const struct attribute_group *attr_groups[] = {
+               &i915_pmu_format_attr_group,
+               &pmu->events_attr_group,
+               &i915_pmu_cpumask_attr_group,
+               NULL
+       };
+
        int ret = -ENOMEM;
 
        if (INTEL_GEN(i915) <= 2) {
@@ -1128,6 +1122,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
        spin_lock_init(&pmu->lock);
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
+       pmu->cpuhp.slot = CPUHP_INVALID;
 
        if (!is_igp(i915)) {
                pmu->name = kasprintf(GFP_KERNEL,
@@ -1143,11 +1138,16 @@ void i915_pmu_register(struct drm_i915_private *i915)
        if (!pmu->name)
                goto err;
 
-       i915_pmu_events_attr_group.attrs = create_event_attributes(pmu);
-       if (!i915_pmu_events_attr_group.attrs)
+       pmu->events_attr_group.name = "events";
+       pmu->events_attr_group.attrs = create_event_attributes(pmu);
+       if (!pmu->events_attr_group.attrs)
                goto err_name;
 
-       pmu->base.attr_groups   = i915_pmu_attr_groups;
+       pmu->base.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
+                                       GFP_KERNEL);
+       if (!pmu->base.attr_groups)
+               goto err_attr;
+
        pmu->base.task_ctx_nr   = perf_invalid_context;
        pmu->base.event_init    = i915_pmu_event_init;
        pmu->base.add           = i915_pmu_event_add;
@@ -1159,7 +1159,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
        ret = perf_pmu_register(&pmu->base, pmu->name, -1);
        if (ret)
-               goto err_attr;
+               goto err_groups;
 
        ret = i915_pmu_register_cpuhp_state(pmu);
        if (ret)
@@ -1169,6 +1169,8 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
 err_unreg:
        perf_pmu_unregister(&pmu->base);
+err_groups:
+       kfree(pmu->base.attr_groups);
 err_attr:
        pmu->base.event_init = NULL;
        free_event_attributes(pmu);
@@ -1194,6 +1196,7 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
 
        perf_pmu_unregister(&pmu->base);
        pmu->base.event_init = NULL;
+       kfree(pmu->base.attr_groups);
        if (!is_igp(i915))
                kfree(pmu->name);
        free_event_attributes(pmu);
index 6c1647c5daf255ff4d27fb538dd2ec358ed782e2..f1d6cad0d7d576caa3999bf0b62fdfe9b9e656d2 100644 (file)
@@ -39,9 +39,12 @@ struct i915_pmu_sample {
 
 struct i915_pmu {
        /**
-        * @node: List node for CPU hotplug handling.
+        * @cpuhp: Struct used for CPU hotplug handling.
         */
-       struct hlist_node node;
+       struct {
+               struct hlist_node node;
+               enum cpuhp_state slot;
+       } cpuhp;
        /**
         * @base: PMU base.
         */
@@ -104,6 +107,10 @@ struct i915_pmu {
         * @sleep_last: Last time GT parked for RC6 estimation.
         */
        ktime_t sleep_last;
+       /**
+        * @events_attr_group: Device events attribute group.
+        */
+       struct attribute_group events_attr_group;
        /**
         * @i915_attr: Memory block holding device attributes.
         */
index 78a5f5d3c0700d601108d80225051b3aa1841efa..f56b046a32de19e255b69e9baaeff6fd56d7d29a 100644 (file)
@@ -595,6 +595,8 @@ static void __i915_request_ctor(void *arg)
        i915_sw_fence_init(&rq->submit, submit_notify);
        i915_sw_fence_init(&rq->semaphore, semaphore_notify);
 
+       dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0);
+
        rq->file_priv = NULL;
        rq->capture_list = NULL;
 
@@ -653,25 +655,30 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
                }
        }
 
-       ret = intel_timeline_get_seqno(tl, rq, &seqno);
-       if (ret)
-               goto err_free;
-
        rq->i915 = ce->engine->i915;
        rq->context = ce;
        rq->engine = ce->engine;
        rq->ring = ce->ring;
        rq->execution_mask = ce->engine->mask;
 
+       kref_init(&rq->fence.refcount);
+       rq->fence.flags = 0;
+       rq->fence.error = 0;
+       INIT_LIST_HEAD(&rq->fence.cb_list);
+
+       ret = intel_timeline_get_seqno(tl, rq, &seqno);
+       if (ret)
+               goto err_free;
+
+       rq->fence.context = tl->fence_context;
+       rq->fence.seqno = seqno;
+
        RCU_INIT_POINTER(rq->timeline, tl);
        RCU_INIT_POINTER(rq->hwsp_cacheline, tl->hwsp_cacheline);
        rq->hwsp_seqno = tl->hwsp_seqno;
 
        rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */
 
-       dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock,
-                      tl->fence_context, seqno);
-
        /* We bump the ref for the fence chain */
        i915_sw_fence_reinit(&i915_request_get(rq)->submit);
        i915_sw_fence_reinit(&i915_request_get(rq)->semaphore);
index 5d96cfba40f88978e76053d1a010f8a1579559fd..34b654b4e58af2b7fb3eb22b4bcecd65c74c9e2f 100644 (file)
@@ -423,8 +423,6 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
 
        if (!node_signaled(signal)) {
                INIT_LIST_HEAD(&dep->dfs_link);
-               list_add(&dep->wait_link, &signal->waiters_list);
-               list_add(&dep->signal_link, &node->signalers_list);
                dep->signaler = signal;
                dep->waiter = node;
                dep->flags = flags;
@@ -434,6 +432,10 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
                    !node_started(signal))
                        node->flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
 
+               /* All set, now publish. Beware the lockless walkers. */
+               list_add(&dep->signal_link, &node->signalers_list);
+               list_add_rcu(&dep->wait_link, &signal->waiters_list);
+
                /*
                 * As we do not allow WAIT to preempt inflight requests,
                 * once we have executed a request, along with triggering
index c47261ae86eab09b1341059a3ec9cb36db6767a8..632d6953c78da92bfe4edbcf58407984a0c39c47 100644 (file)
@@ -8,9 +8,8 @@
 #include "i915_drv.h"
 #include "i915_utils.h"
 
-#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
-#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
-                   "providing the dmesg log by booting with drm.debug=0xf"
+#define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
+#define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
 
 void
 __i915_printk(struct drm_i915_private *dev_priv, const char *level,
index 983afeaee737ea27593f988ae5eb00a68e0a1c76..748cd379065f1103240ecf4dd4af72d635f63318 100644 (file)
@@ -796,12 +796,41 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
        return true;
 }
 
+#define GBIF_CLIENT_HALT_MASK             BIT(0)
+#define GBIF_ARB_HALT_MASK                BIT(1)
+
+static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
+{
+       struct msm_gpu *gpu = &adreno_gpu->base;
+
+       if (!a6xx_has_gbif(adreno_gpu)) {
+               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
+               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
+                                                               0xf) == 0xf);
+               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+
+               return;
+       }
+
+       /* Halt new client requests on GBIF */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
+       spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+                       (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
+
+       /* Halt all AXI requests on GBIF */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
+       spin_until((gpu_read(gpu,  REG_A6XX_GBIF_HALT_ACK) &
+                       (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
+
+       /* The GBIF halt needs to be explicitly cleared */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
+}
+
 /* Gracefully try to shut down the GMU and by extension the GPU */
 static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
 {
        struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
        struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
-       struct msm_gpu *gpu = &adreno_gpu->base;
        u32 val;
 
        /*
@@ -819,11 +848,7 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
                        return;
                }
 
-               /* Clear the VBIF pipe before shutting down */
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
-               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 0xf)
-                       == 0xf);
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+               a6xx_bus_clear_pending_transactions(adreno_gpu);
 
                /* tell the GMU we want to slumber */
                a6xx_gmu_notify_slumber(gmu);
index daf07800cde02a1ecc4797508dc1a631f38892da..68af24150de57c626f31231a06ab364b844da1b9 100644 (file)
@@ -378,18 +378,6 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
        int ret;
 
-       /*
-        * During a previous slumber, GBIF halt is asserted to ensure
-        * no further transaction can go through GPU before GPU
-        * headswitch is turned off.
-        *
-        * This halt is deasserted once headswitch goes off but
-        * incase headswitch doesn't goes off clear GBIF halt
-        * here to ensure GPU wake-up doesn't fail because of
-        * halted GPU transactions.
-        */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
-
        /* Make sure the GMU keeps the GPU on while we set it up */
        a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
 
@@ -470,10 +458,12 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        /* Select CP0 to always count cycles */
        gpu_write(gpu, REG_A6XX_CP_PERFCTR_CP_SEL_0, PERF_CP_ALWAYS_COUNT);
 
-       gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, 2 << 21);
+       if (adreno_is_a630(adreno_gpu)) {
+               gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, 2 << 21);
+       }
 
        /* Enable fault detection */
        gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
@@ -748,39 +738,6 @@ static const u32 a6xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
        REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A6XX_CP_RB_CNTL),
 };
 
-#define GBIF_CLIENT_HALT_MASK             BIT(0)
-#define GBIF_ARB_HALT_MASK                BIT(1)
-
-static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
-{
-       struct msm_gpu *gpu = &adreno_gpu->base;
-
-       if(!a6xx_has_gbif(adreno_gpu)){
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
-               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
-                                                               0xf) == 0xf);
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
-
-               return;
-       }
-
-       /* Halt new client requests on GBIF */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
-       spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
-                       (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
-
-       /* Halt all AXI requests on GBIF */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
-       spin_until((gpu_read(gpu,  REG_A6XX_GBIF_HALT_ACK) &
-                       (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
-
-       /*
-        * GMU needs DDR access in slumber path. Deassert GBIF halt now
-        * to allow for GMU to access system memory.
-        */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
-}
-
 static int a6xx_pm_resume(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -805,16 +762,6 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
 
        devfreq_suspend_device(gpu->devfreq.devfreq);
 
-       /*
-        * Make sure the GMU is idle before continuing (because some transitions
-        * may use VBIF
-        */
-       a6xx_gmu_wait_for_idle(&a6xx_gpu->gmu);
-
-       /* Clear the VBIF pipe before shutting down */
-       /* FIXME: This accesses the GPU - do we need to make sure it is on? */
-       a6xx_bus_clear_pending_transactions(adreno_gpu);
-
        return a6xx_gmu_stop(a6xx_gpu);
 }
 
index eda11abc5f011f1a8ef8bab3feb19274d6c0277f..e450e0b97211533160878013cb72ac0a358d927b 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "a6xx_gmu.h"
 #include "a6xx_gmu.xml.h"
+#include "a6xx_gpu.h"
 
 #define HFI_MSG_ID(val) [val] = #val
 
@@ -216,48 +217,82 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
                NULL, 0);
 }
 
-static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
+static void a618_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
 {
-       struct a6xx_hfi_msg_bw_table msg = { 0 };
+       /* Send a single "off" entry since the 618 GMU doesn't do bus scaling */
+       msg->bw_level_num = 1;
+
+       msg->ddr_cmds_num = 3;
+       msg->ddr_wait_bitmask = 0x01;
+
+       msg->ddr_cmds_addrs[0] = 0x50000;
+       msg->ddr_cmds_addrs[1] = 0x5003c;
+       msg->ddr_cmds_addrs[2] = 0x5000c;
+
+       msg->ddr_cmds_data[0][0] =  0x40000000;
+       msg->ddr_cmds_data[0][1] =  0x40000000;
+       msg->ddr_cmds_data[0][2] =  0x40000000;
 
        /*
-        * The sdm845 GMU doesn't do bus frequency scaling on its own but it
-        * does need at least one entry in the list because it might be accessed
-        * when the GMU is shutting down. Send a single "off" entry.
+        * These are the CX (CNOC) votes - these are used by the GMU but the
+        * votes are known and fixed for the target
         */
+       msg->cnoc_cmds_num = 1;
+       msg->cnoc_wait_bitmask = 0x01;
+
+       msg->cnoc_cmds_addrs[0] = 0x5007c;
+       msg->cnoc_cmds_data[0][0] =  0x40000000;
+       msg->cnoc_cmds_data[1][0] =  0x60000001;
+}
 
-       msg.bw_level_num = 1;
+static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
+{
+       /* Send a single "off" entry since the 630 GMU doesn't do bus scaling */
+       msg->bw_level_num = 1;
 
-       msg.ddr_cmds_num = 3;
-       msg.ddr_wait_bitmask = 0x07;
+       msg->ddr_cmds_num = 3;
+       msg->ddr_wait_bitmask = 0x07;
 
-       msg.ddr_cmds_addrs[0] = 0x50000;
-       msg.ddr_cmds_addrs[1] = 0x5005c;
-       msg.ddr_cmds_addrs[2] = 0x5000c;
+       msg->ddr_cmds_addrs[0] = 0x50000;
+       msg->ddr_cmds_addrs[1] = 0x5005c;
+       msg->ddr_cmds_addrs[2] = 0x5000c;
 
-       msg.ddr_cmds_data[0][0] =  0x40000000;
-       msg.ddr_cmds_data[0][1] =  0x40000000;
-       msg.ddr_cmds_data[0][2] =  0x40000000;
+       msg->ddr_cmds_data[0][0] =  0x40000000;
+       msg->ddr_cmds_data[0][1] =  0x40000000;
+       msg->ddr_cmds_data[0][2] =  0x40000000;
 
        /*
         * These are the CX (CNOC) votes.  This is used but the values for the
         * sdm845 GMU are known and fixed so we can hard code them.
         */
 
-       msg.cnoc_cmds_num = 3;
-       msg.cnoc_wait_bitmask = 0x05;
+       msg->cnoc_cmds_num = 3;
+       msg->cnoc_wait_bitmask = 0x05;
 
-       msg.cnoc_cmds_addrs[0] = 0x50034;
-       msg.cnoc_cmds_addrs[1] = 0x5007c;
-       msg.cnoc_cmds_addrs[2] = 0x5004c;
+       msg->cnoc_cmds_addrs[0] = 0x50034;
+       msg->cnoc_cmds_addrs[1] = 0x5007c;
+       msg->cnoc_cmds_addrs[2] = 0x5004c;
 
-       msg.cnoc_cmds_data[0][0] =  0x40000000;
-       msg.cnoc_cmds_data[0][1] =  0x00000000;
-       msg.cnoc_cmds_data[0][2] =  0x40000000;
+       msg->cnoc_cmds_data[0][0] =  0x40000000;
+       msg->cnoc_cmds_data[0][1] =  0x00000000;
+       msg->cnoc_cmds_data[0][2] =  0x40000000;
+
+       msg->cnoc_cmds_data[1][0] =  0x60000001;
+       msg->cnoc_cmds_data[1][1] =  0x20000001;
+       msg->cnoc_cmds_data[1][2] =  0x60000001;
+}
+
+
+static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
+{
+       struct a6xx_hfi_msg_bw_table msg = { 0 };
+       struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+       struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 
-       msg.cnoc_cmds_data[1][0] =  0x60000001;
-       msg.cnoc_cmds_data[1][1] =  0x20000001;
-       msg.cnoc_cmds_data[1][2] =  0x60000001;
+       if (adreno_is_a618(adreno_gpu))
+               a618_build_bw_table(&msg);
+       else
+               a6xx_build_bw_table(&msg);
 
        return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg),
                NULL, 0);
index 528632690f1ef4f6d0ab476f10d3c26e68540d1c..a05282dede91b6530d4a5d01a1df88dd90ee84a1 100644 (file)
@@ -255,13 +255,13 @@ static const struct dpu_format dpu_format_map[] = {
 
        INTERLEAVED_RGB_FMT(RGB565,
                0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-               C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
+               C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
                false, 2, 0,
                DPU_FETCH_LINEAR, 1),
 
        INTERLEAVED_RGB_FMT(BGR565,
                0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-               C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
+               C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
                false, 2, 0,
                DPU_FETCH_LINEAR, 1),
 
index 29705e773a4b7035d6f9981a6a846deaf60231a8..80d3cfc140070d0cd3006981fb473a3cc453710e 100644 (file)
@@ -12,6 +12,7 @@
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
 
+#define HW_REV                         0x0
 #define HW_INTR_STATUS                 0x0010
 
 /* Max BW defined in KBps */
@@ -22,6 +23,17 @@ struct dpu_irq_controller {
        struct irq_domain *domain;
 };
 
+struct dpu_hw_cfg {
+       u32 val;
+       u32 offset;
+};
+
+struct dpu_mdss_hw_init_handler {
+       u32 hw_rev;
+       u32 hw_reg_count;
+       struct dpu_hw_cfg* hw_cfg;
+};
+
 struct dpu_mdss {
        struct msm_mdss base;
        void __iomem *mmio;
@@ -32,6 +44,44 @@ struct dpu_mdss {
        u32 num_paths;
 };
 
+static struct dpu_hw_cfg hw_cfg[] = {
+    {
+       /* UBWC global settings */
+       .val = 0x1E,
+       .offset = 0x144,
+    }
+};
+
+static struct dpu_mdss_hw_init_handler cfg_handler[] = {
+    { .hw_rev = DPU_HW_VER_620,
+      .hw_reg_count = ARRAY_SIZE(hw_cfg),
+      .hw_cfg = hw_cfg
+    },
+};
+
+static void dpu_mdss_hw_init(struct dpu_mdss *dpu_mdss, u32 hw_rev)
+{
+       int i;
+       u32 count = 0;
+       struct dpu_hw_cfg *hw_cfg = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) {
+               if (cfg_handler[i].hw_rev == hw_rev) {
+                       hw_cfg = cfg_handler[i].hw_cfg;
+                       count = cfg_handler[i].hw_reg_count;
+                       break;
+           }
+       }
+
+       for (i = 0; i < count; i++ ) {
+               writel_relaxed(hw_cfg->val,
+                       dpu_mdss->mmio + hw_cfg->offset);
+               hw_cfg++;
+       }
+
+    return;
+}
+
 static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev,
                                                struct dpu_mdss *dpu_mdss)
 {
@@ -174,12 +224,18 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
        struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
        struct dss_module_power *mp = &dpu_mdss->mp;
        int ret;
+       u32 mdss_rev;
 
        dpu_mdss_icc_request_bw(mdss);
 
        ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
-       if (ret)
+       if (ret) {
                DPU_ERROR("clock enable failed, ret:%d\n", ret);
+               return ret;
+       }
+
+       mdss_rev = readl_relaxed(dpu_mdss->mmio + HW_REV);
+       dpu_mdss_hw_init(dpu_mdss, mdss_rev);
 
        return ret;
 }
index 05cc04f729d638963325b03a288ad502cccae822..e1cc541e0ef2e37a44d20378c1e3b37a493578d6 100644 (file)
@@ -1109,8 +1109,8 @@ static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
        ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
                                                msecs_to_jiffies(50));
        if (ret == 0)
-               dev_warn(dev->dev, "pp done time out, lm=%d\n",
-                        mdp5_cstate->pipeline.mixer->lm);
+               dev_warn_ratelimited(dev->dev, "pp done time out, lm=%d\n",
+                                    mdp5_cstate->pipeline.mixer->lm);
 }
 
 static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
index 104115d112eba6aebc87cb464c9b89a3c513b945..4864b9558f65ab6674a2df30444262afcca09405 100644 (file)
@@ -336,7 +336,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
        return num;
 }
 
-static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
+static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
        int id = dsi_mgr_connector_get_id(connector);
@@ -506,6 +506,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
        struct mipi_dsi_host *host = msm_dsi->host;
        struct drm_panel *panel = msm_dsi->panel;
+       struct msm_dsi_pll *src_pll;
        bool is_dual_dsi = IS_DUAL_DSI();
        int ret;
 
@@ -539,6 +540,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
                                                                id, ret);
        }
 
+       /* Save PLL status if it is a clock source */
+       src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+       msm_dsi_pll_save_state(src_pll);
+
        ret = msm_dsi_host_power_off(host);
        if (ret)
                pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
index b0cfa67d2a57806bc1e9cd7cb4846ebcfe8c08bd..f509ebd77500f43bbcd846de9c1ff44e5ec2eb2e 100644 (file)
@@ -724,10 +724,6 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
        if (!phy || !phy->cfg->ops.disable)
                return;
 
-       /* Save PLL status if it is a clock source */
-       if (phy->usecase != MSM_DSI_PHY_SLAVE)
-               msm_dsi_pll_save_state(phy->pll);
-
        phy->cfg->ops.disable(phy);
 
        dsi_phy_regulator_disable(phy);
index 1c894548dd725c8365bc4eae9b98446ea36739e1..6ac04fc303f5699ba29b356e714c35ea96b6f12e 100644 (file)
@@ -411,6 +411,12 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
        if (pll_10nm->slave)
                dsi_pll_enable_pll_bias(pll_10nm->slave);
 
+       rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);
+       if (rc) {
+               pr_err("vco_set_rate failed, rc=%d\n", rc);
+               return rc;
+       }
+
        /* Start PLL */
        pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
                  0x01);
index 890315291b01eff70a13ca6a3232517f970f4e65..bb737f9281e692f2adf4a3c8e93d7081b022b7ea 100644 (file)
@@ -458,6 +458,8 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                asyw->clr.ntfy = armw->ntfy.handle != 0;
                asyw->clr.sema = armw->sema.handle != 0;
                asyw->clr.xlut = armw->xlut.handle != 0;
+               if (asyw->clr.xlut && asyw->visible)
+                       asyw->set.xlut = asyw->xlut.handle != 0;
                asyw->clr.csc  = armw->csc.valid;
                if (wndw->func->image_clr)
                        asyw->clr.image = armw->image.handle[0] != 0;
index c7d700916eae7356fa8f9e7e501c9a1efe255967..8ebbe16560083dc573b41dc0336d217264d0909d 100644 (file)
@@ -2579,6 +2579,7 @@ nv166_chipset = {
 static const struct nvkm_device_chip
 nv167_chipset = {
        .name = "TU117",
+       .acr = tu102_acr_new,
        .bar = tu102_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
@@ -2607,6 +2608,7 @@ nv167_chipset = {
        .disp = tu102_disp_new,
        .dma = gv100_dma_new,
        .fifo = tu102_fifo_new,
+       .gr = tu102_gr_new,
        .nvdec[0] = gm107_nvdec_new,
        .nvenc[0] = gm107_nvenc_new,
        .sec2 = tu102_sec2_new,
@@ -2615,6 +2617,7 @@ nv167_chipset = {
 static const struct nvkm_device_chip
 nv168_chipset = {
        .name = "TU116",
+       .acr = tu102_acr_new,
        .bar = tu102_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
@@ -2643,6 +2646,7 @@ nv168_chipset = {
        .disp = tu102_disp_new,
        .dma = gv100_dma_new,
        .fifo = tu102_fifo_new,
+       .gr = tu102_gr_new,
        .nvdec[0] = gm107_nvdec_new,
        .nvenc[0] = gm107_nvenc_new,
        .sec2 = tu102_sec2_new,
index 454668b1cf54d5975f59a6694c5fd474845fb0f5..a9efa4d78be92a808f41e9a9b9329ec0d99cb5f6 100644 (file)
@@ -164,6 +164,32 @@ MODULE_FIRMWARE("nvidia/tu106/gr/sw_nonctx.bin");
 MODULE_FIRMWARE("nvidia/tu106/gr/sw_bundle_init.bin");
 MODULE_FIRMWARE("nvidia/tu106/gr/sw_method_init.bin");
 
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_data.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_data.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_ctx.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_nonctx.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_bundle_init.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_method_init.bin");
+
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_data.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_data.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_ctx.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_nonctx.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_bundle_init.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_method_init.bin");
+
 static const struct gf100_gr_fwif
 tu102_gr_fwif[] = {
        { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr },
index 7f4b89d82d320a0b7ec6e0e2fe4b981b569ff2b0..d28d8f36ae2484ac4d237ad0fb3750b2d52b53b7 100644 (file)
@@ -107,6 +107,12 @@ MODULE_FIRMWARE("nvidia/tu104/acr/ucode_unload.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/unload_bl.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_unload.bin");
 
+MODULE_FIRMWARE("nvidia/tu116/acr/unload_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_unload.bin");
+
+MODULE_FIRMWARE("nvidia/tu117/acr/unload_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_unload.bin");
+
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_unload_fwif[] = {
        {  0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 },
@@ -130,6 +136,8 @@ tu102_acr_asb_0 = {
 MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin");
 MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_asb.bin");
 
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_asb_fwif[] = {
@@ -154,6 +162,12 @@ MODULE_FIRMWARE("nvidia/tu104/acr/ucode_ahesasc.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/bl.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_ahesasc.bin");
 
+MODULE_FIRMWARE("nvidia/tu116/acr/bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_ahesasc.bin");
+
+MODULE_FIRMWARE("nvidia/tu117/acr/bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_ahesasc.bin");
+
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_ahesasc_fwif[] = {
        {  0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 },
index 389bad312bf279bd15102d121728e2a11607473e..10ff5d053f7ea4e0f0645028906da0d6acc2a031 100644 (file)
@@ -51,3 +51,5 @@ MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin");
index 7157dfd7dea3c98661fb604eeb65192bece911a1..9a1a72a748e724ca5bac36d4e05c82eb4ccd1f93 100644 (file)
@@ -280,12 +280,8 @@ static void panfrost_job_cleanup(struct kref *ref)
        }
 
        if (job->bos) {
-               struct panfrost_gem_object *bo;
-
-               for (i = 0; i < job->bo_count; i++) {
-                       bo = to_panfrost_bo(job->bos[i]);
+               for (i = 0; i < job->bo_count; i++)
                        drm_gem_object_put_unlocked(job->bos[i]);
-               }
 
                kvfree(job->bos);
        }
index 763cfca886a73a7c90d8d6df9e0e4e36c7d2bf7d..3107b0738e401720a5ef3ceaf47ba3ddd6cc6c26 100644 (file)
@@ -151,7 +151,12 @@ u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
        as = mmu->as;
        if (as >= 0) {
                int en = atomic_inc_return(&mmu->as_count);
-               WARN_ON(en >= NUM_JOB_SLOTS);
+
+               /*
+                * AS can be retained by active jobs or a perfcnt context,
+                * hence the '+ 1' here.
+                */
+               WARN_ON(en >= (NUM_JOB_SLOTS + 1));
 
                list_move(&mmu->list, &pfdev->as_lru_list);
                goto out;
index 684820448be31c7d459a1f139b5003b8cacd1968..6913578d5aa7211de705877f42d8eb210be5289c 100644 (file)
@@ -73,7 +73,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
        struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_gem_shmem_object *bo;
-       u32 cfg;
+       u32 cfg, as;
        int ret;
 
        if (user == perfcnt->user)
@@ -126,12 +126,8 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
 
        perfcnt->user = user;
 
-       /*
-        * Always use address space 0 for now.
-        * FIXME: this needs to be updated when we start using different
-        * address space.
-        */
-       cfg = GPU_PERFCNT_CFG_AS(0) |
+       as = panfrost_mmu_as_get(pfdev, perfcnt->mapping->mmu);
+       cfg = GPU_PERFCNT_CFG_AS(as) |
              GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_MANUAL);
 
        /*
@@ -195,6 +191,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
        drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, perfcnt->buf);
        perfcnt->buf = NULL;
        panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
+       panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
        panfrost_gem_mapping_put(perfcnt->mapping);
        perfcnt->mapping = NULL;
        pm_runtime_mark_last_busy(pfdev->dev);
index fd74e261118595e8fb4080764ee93eb961935319..8696af1ee14dc7705b9a98f6869d69526d6a1ddd 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/mmu_notifier.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
@@ -325,6 +326,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
                            const struct pci_device_id *ent)
 {
        unsigned long flags = 0;
+       struct drm_device *dev;
        int ret;
 
        if (!ent)
@@ -365,7 +367,44 @@ static int radeon_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
-       return drm_get_pci_dev(pdev, ent, &kms_driver);
+       dev = drm_dev_alloc(&kms_driver, &pdev->dev);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto err_free;
+
+       dev->pdev = pdev;
+#ifdef __alpha__
+       dev->hose = pdev->sysdata;
+#endif
+
+       pci_set_drvdata(pdev, dev);
+
+       if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
+               dev->agp = drm_agp_init(dev);
+       if (dev->agp) {
+               dev->agp->agp_mtrr = arch_phys_wc_add(
+                       dev->agp->agp_info.aper_base,
+                       dev->agp->agp_info.aper_size *
+                       1024 * 1024);
+       }
+
+       ret = drm_dev_register(dev, ent->driver_data);
+       if (ret)
+               goto err_agp;
+
+       return 0;
+
+err_agp:
+       if (dev->agp)
+               arch_phys_wc_del(dev->agp->agp_mtrr);
+       kfree(dev->agp);
+       pci_disable_device(pdev);
+err_free:
+       drm_dev_put(dev);
+       return ret;
 }
 
 static void
@@ -575,7 +614,7 @@ radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER,
+           DRIVER_GEM | DRIVER_RENDER,
        .load = radeon_driver_load_kms,
        .open = radeon_driver_open_kms,
        .postclose = radeon_driver_postclose_kms,
index d24f23a8165602a547608777a3cc004e7cc9cc22..dd2f19b8022bd2c215fed2a257e90307b666ea86 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/vga_switcheroo.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
@@ -77,6 +78,11 @@ void radeon_driver_unload_kms(struct drm_device *dev)
        radeon_modeset_fini(rdev);
        radeon_device_fini(rdev);
 
+       if (dev->agp)
+               arch_phys_wc_del(dev->agp->agp_mtrr);
+       kfree(dev->agp);
+       dev->agp = NULL;
+
 done_free:
        kfree(rdev);
        dev->dev_private = NULL;
index ceac7af9a172ddf4842e4f2f0500d2829427d488..29e367db6118ba125ec9ad23fc0cba393b2a7ca2 100644 (file)
@@ -53,6 +53,7 @@ cmdline_test(drm_cmdline_test_rotate_0)
 cmdline_test(drm_cmdline_test_rotate_90)
 cmdline_test(drm_cmdline_test_rotate_180)
 cmdline_test(drm_cmdline_test_rotate_270)
+cmdline_test(drm_cmdline_test_rotate_multiple)
 cmdline_test(drm_cmdline_test_rotate_invalid_val)
 cmdline_test(drm_cmdline_test_rotate_truncated)
 cmdline_test(drm_cmdline_test_hmirror)
index 520f3e66a384a27f694a92f823a489ca439a88bf..d96cd890def6eafcd8773e9180928255072bdd62 100644 (file)
@@ -856,6 +856,17 @@ static int drm_cmdline_test_rotate_270(void *ignored)
        return 0;
 }
 
+static int drm_cmdline_test_rotate_multiple(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90",
+                                                         &no_connector,
+                                                         &mode));
+
+       return 0;
+}
+
 static int drm_cmdline_test_rotate_invalid_val(void *ignored)
 {
        struct drm_cmdline_mode mode = { };
@@ -888,7 +899,7 @@ static int drm_cmdline_test_hmirror(void *ignored)
        FAIL_ON(!mode.specified);
        FAIL_ON(mode.xres != 720);
        FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_X);
+       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X));
 
        FAIL_ON(mode.refresh_specified);
 
@@ -913,7 +924,7 @@ static int drm_cmdline_test_vmirror(void *ignored)
        FAIL_ON(!mode.specified);
        FAIL_ON(mode.xres != 720);
        FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_Y);
+       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y));
 
        FAIL_ON(mode.refresh_specified);
 
index ae79a7c667372e6e54b8302565870c3f24b2ce85..fa704153cb00d5f7fa7d0185acd1f953fdd37754 100644 (file)
@@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (data->has_sp) {
                input2 = input_allocate_device();
                if (!input2) {
-                       input_free_device(input2);
+                       ret = -ENOMEM;
                        goto exit;
                }
 
index 6ac8becc2372efdd303ba29d14a246e9f5290239..d732d1d10cafb7bbafbf27ec59ff17bd5aae2c94 100644 (file)
@@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                unsigned long **bit, int *max)
 {
        if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
-                       usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
+                       usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
+                       usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
                /* The fn key on Apple USB keyboards */
                set_bit(EV_REP, hi->input->evbit);
                hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
index 3f6abd190df43ef17cb6080505fe7761c38324fe..db6da21ade06315c457d087447cecf563eac8c55 100644 (file)
@@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
 struct bigben_device {
        struct hid_device *hid;
        struct hid_report *report;
+       bool removed;
        u8 led_state;         /* LED1 = 1 .. LED4 = 8 */
        u8 right_motor_on;    /* right motor off/on 0/1 */
        u8 left_motor_force;  /* left motor force 0-255 */
@@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
                struct bigben_device, worker);
        struct hid_field *report_field = bigben->report->field[0];
 
+       if (bigben->removed)
+               return;
+
        if (bigben->work_led) {
                bigben->work_led = false;
                report_field->value[0] = 0x01; /* 1 = led message */
@@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
 static int hid_bigben_play_effect(struct input_dev *dev, void *data,
                         struct ff_effect *effect)
 {
-       struct bigben_device *bigben = data;
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct bigben_device *bigben = hid_get_drvdata(hid);
        u8 right_motor_on;
        u8 left_motor_force;
 
+       if (!bigben) {
+               hid_err(hid, "no device data\n");
+               return 0;
+       }
+
        if (effect->type != FF_RUMBLE)
                return 0;
 
@@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
 {
        struct bigben_device *bigben = hid_get_drvdata(hid);
 
+       bigben->removed = true;
        cancel_work_sync(&bigben->worker);
-       hid_hw_close(hid);
        hid_hw_stop(hid);
 }
 
@@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
                return -ENOMEM;
        hid_set_drvdata(hid, bigben);
        bigben->hid = hid;
+       bigben->removed = false;
 
        error = hid_parse(hid);
        if (error) {
@@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,
 
        INIT_WORK(&bigben->worker, bigben_worker);
 
-       error = input_ff_create_memless(hidinput->input, bigben,
+       error = input_ff_create_memless(hidinput->input, NULL,
                hid_bigben_play_effect);
        if (error)
-               return error;
+               goto error_hw_stop;
 
        name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
 
@@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
                        sizeof(struct led_classdev) + name_sz,
                        GFP_KERNEL
                );
-               if (!led)
-                       return -ENOMEM;
+               if (!led) {
+                       error = -ENOMEM;
+                       goto error_hw_stop;
+               }
                name = (void *)(&led[1]);
                snprintf(name, name_sz,
                        "%s:red:bigben%d",
@@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
                bigben->leds[n] = led;
                error = devm_led_classdev_register(&hid->dev, led);
                if (error)
-                       return error;
+                       goto error_hw_stop;
        }
 
        /* initial state: LED1 is on, no rumble effect */
@@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
        hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
 
        return 0;
+
+error_hw_stop:
+       hid_hw_stop(hid);
+       return error;
 }
 
 static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
index 851fe54ea59e7c2636ab204372c49b749a136014..359616e3efbbb244e633b4a37ae6361c30abf19f 100644 (file)
@@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
 
        rsize = ((report->size - 1) >> 3) + 1;
 
-       if (rsize > HID_MAX_BUFFER_SIZE)
+       if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
+               rsize = HID_MAX_BUFFER_SIZE - 1;
+       else if (rsize > HID_MAX_BUFFER_SIZE)
                rsize = HID_MAX_BUFFER_SIZE;
 
        if (csize < rsize) {
index c436e12feb23315f141362dccc38c2c549c8d9f9..6c55682c597409d1fcdbfbaad7a4974010b50857 100644 (file)
@@ -41,8 +41,9 @@ static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
        /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
-       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
-                        USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_SYNAPTICS,
+                    USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index 70e1cb928bf038876cd603e99302ea7e5687c426..094f4f1b6555b49315d44632a70cb8c6205f24db 100644 (file)
@@ -1256,36 +1256,35 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
 {
        int status;
 
-       long charge_sts = (long)data[2];
+       long flags = (long) data[2];
 
-       *level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
-       switch (data[2] & 0xe0) {
-       case 0x00:
-               status = POWER_SUPPLY_STATUS_CHARGING;
-               break;
-       case 0x20:
-               status = POWER_SUPPLY_STATUS_FULL;
-               *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-               break;
-       case 0x40:
+       if (flags & 0x80)
+               switch (flags & 0x07) {
+               case 0:
+                       status = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               case 1:
+                       status = POWER_SUPPLY_STATUS_FULL;
+                       *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+                       break;
+               case 2:
+                       status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       break;
+               default:
+                       status = POWER_SUPPLY_STATUS_UNKNOWN;
+                       break;
+               }
+       else
                status = POWER_SUPPLY_STATUS_DISCHARGING;
-               break;
-       case 0xe0:
-               status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               break;
-       default:
-               status = POWER_SUPPLY_STATUS_UNKNOWN;
-       }
 
        *charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
-       if (test_bit(3, &charge_sts)) {
+       if (test_bit(3, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
        }
-       if (test_bit(4, &charge_sts)) {
+       if (test_bit(4, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
        }
-
-       if (test_bit(5, &charge_sts)) {
+       if (test_bit(5, &flags)) {
                *level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
        }
 
index d31ea82b84c173033dd1a6582122ec9197671fbc..a66f08041a1aa105d1605210c3f70b71d4afbcc3 100644 (file)
@@ -341,6 +341,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                },
                .driver_data = (void *)&sipodev_desc
        },
+       {
+               .ident = "Trekstor SURFBOOK E11B",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
        {
                .ident = "Direkt-Tek DTLAPY116-2",
                .matches = {
index a970b809d778c3c9a74702abe70c9f1f976a06d9..4140dea693e90988d80bac6129458499fb2d03af 100644 (file)
@@ -932,9 +932,9 @@ void hiddev_disconnect(struct hid_device *hid)
        hiddev->exist = 0;
 
        if (hiddev->open) {
-               mutex_unlock(&hiddev->existancelock);
                hid_hw_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
+               mutex_unlock(&hiddev->existancelock);
        } else {
                mutex_unlock(&hiddev->existancelock);
                kfree(hiddev);
index 4cf25458f0b9515e419a6f0b88047bf35809a2e5..0db8ef4fd6e18b7464f3c8e4b6c0de741f8e0998 100644 (file)
@@ -355,7 +355,9 @@ static ssize_t show_str(struct device *dev,
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
        acpi_string val;
+       int ret;
 
+       mutex_lock(&resource->lock);
        switch (attr->index) {
        case 0:
                val = resource->model_number;
@@ -372,8 +374,9 @@ static ssize_t show_str(struct device *dev,
                val = "";
                break;
        }
-
-       return sprintf(buf, "%s\n", val);
+       ret = sprintf(buf, "%s\n", val);
+       mutex_unlock(&resource->lock);
+       return ret;
 }
 
 static ssize_t show_val(struct device *dev,
@@ -817,11 +820,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
 
        resource = acpi_driver_data(device);
 
-       mutex_lock(&resource->lock);
        switch (event) {
        case METER_NOTIFY_CONFIG:
+               mutex_lock(&resource->lock);
                free_capabilities(resource);
                res = read_capabilities(resource);
+               mutex_unlock(&resource->lock);
                if (res)
                        break;
 
@@ -830,15 +834,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                break;
        case METER_NOTIFY_TRIP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
-               update_meter(resource);
                break;
        case METER_NOTIFY_CAP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
-               update_cap(resource);
                break;
        case METER_NOTIFY_INTERVAL:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
-               update_avg_interval(resource);
                break;
        case METER_NOTIFY_CAPPING:
                sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
@@ -848,7 +849,6 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                WARN(1, "Unexpected event %d\n", event);
                break;
        }
-       mutex_unlock(&resource->lock);
 
        acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS,
                                        dev_name(&device->dev), event, 0);
@@ -912,8 +912,8 @@ static int acpi_power_meter_remove(struct acpi_device *device)
        resource = acpi_driver_data(device);
        hwmon_device_unregister(resource->hwmon_dev);
 
-       free_capabilities(resource);
        remove_attrs(resource);
+       free_capabilities(resource);
 
        kfree(resource);
        return 0;
index 7ffadc2da57b537d2638f0829fa778318546a1e3..5a5120121e50725c49a39356ab613b72beb58c97 100644 (file)
@@ -1346,8 +1346,13 @@ w83627ehf_is_visible(const void *drvdata, enum hwmon_sensor_types type,
                /* channel 0.., name 1.. */
                if (!(data->have_temp & (1 << channel)))
                        return 0;
-               if (attr == hwmon_temp_input || attr == hwmon_temp_label)
+               if (attr == hwmon_temp_input)
                        return 0444;
+               if (attr == hwmon_temp_label) {
+                       if (data->temp_label)
+                               return 0444;
+                       return 0;
+               }
                if (channel == 2 && data->temp3_val_only)
                        return 0;
                if (attr == hwmon_temp_max) {
index 5255d3755411b29285b7170aca298b29e4f4a4e9..1de23b4f3809c507f8f23eac1b7e22641963f537 100644 (file)
@@ -171,7 +171,7 @@ static void altr_i2c_init(struct altr_i2c_dev *idev)
        /* SCL Low Time */
        writel(t_low, idev->base + ALTR_I2C_SCL_LOW);
        /* SDA Hold Time, 300ns */
-       writel(div_u64(300 * clk_mhz, 1000), idev->base + ALTR_I2C_SDA_HOLD);
+       writel(3 * clk_mhz / 10, idev->base + ALTR_I2C_SDA_HOLD);
 
        /* Mask all master interrupt bits */
        altr_i2c_int_enable(idev, ALTR_I2C_ALL_IRQ, false);
index 16a67a64284a04c2d58192e1e763a63f3d13f51f..b426fc9569387d431a955fe3f274f87f735c11f9 100644 (file)
 
 #define X1000_I2C_DC_STOP              BIT(9)
 
-static const char * const jz4780_i2c_abrt_src[] = {
-       "ABRT_7B_ADDR_NOACK",
-       "ABRT_10ADDR1_NOACK",
-       "ABRT_10ADDR2_NOACK",
-       "ABRT_XDATA_NOACK",
-       "ABRT_GCALL_NOACK",
-       "ABRT_GCALL_READ",
-       "ABRT_HS_ACKD",
-       "SBYTE_ACKDET",
-       "ABRT_HS_NORSTRT",
-       "SBYTE_NORSTRT",
-       "ABRT_10B_RD_NORSTRT",
-       "ABRT_MASTER_DIS",
-       "ARB_LOST",
-       "SLVFLUSH_TXFIFO",
-       "SLV_ARBLOST",
-       "SLVRD_INTX",
-};
-
 #define JZ4780_I2C_INTST_IGC           BIT(11)
 #define JZ4780_I2C_INTST_ISTT          BIT(10)
 #define JZ4780_I2C_INTST_ISTP          BIT(9)
@@ -576,21 +557,8 @@ done:
 
 static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src)
 {
-       int i;
-
-       dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src);
-       dev_err(&i2c->adap.dev, "device addr=%x\n",
-               jz4780_i2c_readw(i2c, JZ4780_I2C_TAR));
-       dev_err(&i2c->adap.dev, "send cmd count:%d  %d\n",
-               i2c->cmd, i2c->cmd_buf[i2c->cmd]);
-       dev_err(&i2c->adap.dev, "receive data count:%d  %d\n",
-               i2c->cmd, i2c->data_buf[i2c->cmd]);
-
-       for (i = 0; i < 16; i++) {
-               if (src & BIT(i))
-                       dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n",
-                               i, jz4780_i2c_abrt_src[i]);
-       }
+       dev_dbg(&i2c->adap.dev, "txabrt: 0x%08x, cmd: %d, send: %d, recv: %d\n",
+               src, i2c->cmd, i2c->cmd_buf[i2c->cmd], i2c->data_buf[i2c->cmd]);
 }
 
 static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c,
index 1bb99b5563930c810855d2fe2f23e83e8d619147..05c26986637ba3ad8d29d46387d8cb9f45219402 100644 (file)
@@ -361,7 +361,7 @@ static const struct block_device_operations ide_gd_ops = {
        .release                = ide_gd_release,
        .ioctl                  = ide_gd_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl                  = ide_gd_compat_ioctl,
+       .compat_ioctl           = ide_gd_compat_ioctl,
 #endif
        .getgeo                 = ide_gd_getgeo,
        .check_events           = ide_gd_check_events,
index b273e421e9103f9a4aa7652bda41f6c08a9dc7b6..a1a035270cabf0b0dac14542b5f879514c7ce2e1 100644 (file)
@@ -2575,6 +2575,17 @@ isert_wait4logout(struct isert_conn *isert_conn)
        }
 }
 
+static void
+isert_wait4cmds(struct iscsi_conn *conn)
+{
+       isert_info("iscsi_conn %p\n", conn);
+
+       if (conn->sess) {
+               target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+               target_wait_for_sess_cmds(conn->sess->se_sess);
+       }
+}
+
 /**
  * isert_put_unsol_pending_cmds() - Drop commands waiting for
  *     unsolicitate dataout
@@ -2622,6 +2633,7 @@ static void isert_wait_conn(struct iscsi_conn *conn)
 
        ib_drain_qp(isert_conn->qp);
        isert_put_unsol_pending_cmds(conn);
+       isert_wait4cmds(conn);
        isert_wait4logout(isert_conn);
 
        queue_work(isert_release_wq, &isert_conn->release_work);
index 2104fb8afc0660c2516df9dd5a5d4b6c31d21b8b..9f33fdb3bb0516feb086741a2b4ac89a9e6331dc 100644 (file)
@@ -14,8 +14,8 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
-obj-$(CONFIG_ARM_SMMU) += arm-smmu-mod.o
-arm-smmu-mod-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
+obj-$(CONFIG_ARM_SMMU) += arm_smmu.o
+arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
index 2759a8d57b7f91be441012c23c01bb6d6b408907..6be3853a5d978e09b8aeebb02daaec01e3a80cc9 100644 (file)
@@ -2523,6 +2523,7 @@ static int __init early_amd_iommu_init(void)
        struct acpi_table_header *ivrs_base;
        acpi_status status;
        int i, remap_cache_sz, ret = 0;
+       u32 pci_id;
 
        if (!amd_iommu_detected)
                return -ENODEV;
@@ -2610,6 +2611,16 @@ static int __init early_amd_iommu_init(void)
        if (ret)
                goto out;
 
+       /* Disable IOMMU if there's Stoney Ridge graphics */
+       for (i = 0; i < 32; i++) {
+               pci_id = read_pci_config(0, i, 0, 0);
+               if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
+                       pr_info("Disable IOMMU on Stoney Ridge\n");
+                       amd_iommu_disabled = true;
+                       break;
+               }
+       }
+
        /* Disable any previously enabled IOMMUs */
        if (!is_kdump_kernel() || amd_iommu_disabled)
                disable_iommus();
@@ -2718,7 +2729,7 @@ static int __init state_next(void)
                ret = early_amd_iommu_init();
                init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
                if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
-                       pr_info("AMD IOMMU disabled on kernel command-line\n");
+                       pr_info("AMD IOMMU disabled\n");
                        init_state = IOMMU_CMDLINE_DISABLED;
                        ret = -EINVAL;
                }
index 9dc37672bf893bb70808a9fdef0a850eba685f01..6fa6de2b6ad586d933945f74de0bc79ef8691664 100644 (file)
@@ -762,6 +762,11 @@ static int iommu_dummy(struct device *dev)
        return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
 }
 
+static bool attach_deferred(struct device *dev)
+{
+       return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+}
+
 /**
  * is_downstream_to_pci_bridge - test if a device belongs to the PCI
  *                              sub-hierarchy of a candidate PCI-PCI bridge
@@ -2510,8 +2515,7 @@ struct dmar_domain *find_domain(struct device *dev)
 {
        struct device_domain_info *info;
 
-       if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO ||
-                    dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO))
+       if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
                return NULL;
 
        if (dev_is_pci(dev))
@@ -2525,18 +2529,14 @@ struct dmar_domain *find_domain(struct device *dev)
        return NULL;
 }
 
-static struct dmar_domain *deferred_attach_domain(struct device *dev)
+static void do_deferred_attach(struct device *dev)
 {
-       if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
-               struct iommu_domain *domain;
-
-               dev->archdata.iommu = NULL;
-               domain = iommu_get_domain_for_dev(dev);
-               if (domain)
-                       intel_iommu_attach_device(domain, dev);
-       }
+       struct iommu_domain *domain;
 
-       return find_domain(dev);
+       dev->archdata.iommu = NULL;
+       domain = iommu_get_domain_for_dev(dev);
+       if (domain)
+               intel_iommu_attach_device(domain, dev);
 }
 
 static inline struct device_domain_info *
@@ -2916,7 +2916,7 @@ static int identity_mapping(struct device *dev)
        struct device_domain_info *info;
 
        info = dev->archdata.iommu;
-       if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
+       if (info)
                return (info->domain == si_domain);
 
        return 0;
@@ -3587,6 +3587,9 @@ static bool iommu_need_mapping(struct device *dev)
        if (iommu_dummy(dev))
                return false;
 
+       if (unlikely(attach_deferred(dev)))
+               do_deferred_attach(dev);
+
        ret = identity_mapping(dev);
        if (ret) {
                u64 dma_mask = *dev->dma_mask;
@@ -3635,7 +3638,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
 
        BUG_ON(dir == DMA_NONE);
 
-       domain = deferred_attach_domain(dev);
+       domain = find_domain(dev);
        if (!domain)
                return DMA_MAPPING_ERROR;
 
@@ -3855,7 +3858,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
        if (!iommu_need_mapping(dev))
                return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
 
-       domain = deferred_attach_domain(dev);
+       domain = find_domain(dev);
        if (!domain)
                return 0;
 
@@ -3950,7 +3953,11 @@ bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
        int prot = 0;
        int ret;
 
-       domain = deferred_attach_domain(dev);
+       if (unlikely(attach_deferred(dev)))
+               do_deferred_attach(dev);
+
+       domain = find_domain(dev);
+
        if (WARN_ON(dir == DMA_NONE || !domain))
                return DMA_MAPPING_ERROR;
 
@@ -6133,7 +6140,7 @@ intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
 static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
                                           struct device *dev)
 {
-       return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+       return attach_deferred(dev);
 }
 
 static int
index 39759db4f0038c0ec7dd49928b75e6d89e5cae86..4328da0b0a9fdfa35b1d7f951b72e3599d195a31 100644 (file)
@@ -344,21 +344,19 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain)
 {
        struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
 
-       if (WARN_ON(qcom_domain->iommu))    /* forgot to detach? */
-               return;
-
        iommu_put_dma_cookie(domain);
 
-       /* NOTE: unmap can be called after client device is powered off,
-        * for example, with GPUs or anything involving dma-buf.  So we
-        * cannot rely on the device_link.  Make sure the IOMMU is on to
-        * avoid unclocked accesses in the TLB inv path:
-        */
-       pm_runtime_get_sync(qcom_domain->iommu->dev);
-
-       free_io_pgtable_ops(qcom_domain->pgtbl_ops);
-
-       pm_runtime_put_sync(qcom_domain->iommu->dev);
+       if (qcom_domain->iommu) {
+               /*
+                * NOTE: unmap can be called after client device is powered
+                * off, for example, with GPUs or anything involving dma-buf.
+                * So we cannot rely on the device_link.  Make sure the IOMMU
+                * is on to avoid unclocked accesses in the TLB inv path:
+                */
+               pm_runtime_get_sync(qcom_domain->iommu->dev);
+               free_io_pgtable_ops(qcom_domain->pgtbl_ops);
+               pm_runtime_put_sync(qcom_domain->iommu->dev);
+       }
 
        kfree(qcom_domain);
 }
@@ -404,7 +402,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
        struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
        unsigned i;
 
-       if (!qcom_domain->iommu)
+       if (WARN_ON(!qcom_domain->iommu))
                return;
 
        pm_runtime_get_sync(qcom_iommu->dev);
@@ -417,8 +415,6 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
                ctx->domain = NULL;
        }
        pm_runtime_put_sync(qcom_iommu->dev);
-
-       qcom_domain->iommu = NULL;
 }
 
 static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
index 83b1186ffcad0d29893033019ab37fd478e4e180..1259f7f86a211b63e5e11e63ac701fcdc648d421 100644 (file)
@@ -96,6 +96,7 @@ struct its_node {
        struct mutex            dev_alloc_lock;
        struct list_head        entry;
        void __iomem            *base;
+       void __iomem            *sgir_base;
        phys_addr_t             phys_base;
        struct its_cmd_block    *cmd_base;
        struct its_cmd_block    *cmd_write;
@@ -188,6 +189,15 @@ static DEFINE_IDA(its_vpeid_ida);
 #define gic_data_rdist_rd_base()       (gic_data_rdist()->rd_base)
 #define gic_data_rdist_vlpi_base()     (gic_data_rdist_rd_base() + SZ_128K)
 
+/*
+ * Skip ITSs that have no vLPIs mapped, unless we're on GICv4.1, as we
+ * always have vSGIs mapped.
+ */
+static bool require_its_list_vmovp(struct its_vm *vm, struct its_node *its)
+{
+       return (gic_rdists->has_rvpeid || vm->vlpi_count[its->list_nr]);
+}
+
 static u16 get_its_list(struct its_vm *vm)
 {
        struct its_node *its;
@@ -197,7 +207,7 @@ static u16 get_its_list(struct its_vm *vm)
                if (!is_v4(its))
                        continue;
 
-               if (vm->vlpi_count[its->list_nr])
+               if (require_its_list_vmovp(vm, its))
                        __set_bit(its->list_nr, &its_list);
        }
 
@@ -239,15 +249,41 @@ static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
        return NULL;
 }
 
-static int irq_to_cpuid(struct irq_data *d)
+static int vpe_to_cpuid_lock(struct its_vpe *vpe, unsigned long *flags)
+{
+       raw_spin_lock_irqsave(&vpe->vpe_lock, *flags);
+       return vpe->col_idx;
+}
+
+static void vpe_to_cpuid_unlock(struct its_vpe *vpe, unsigned long flags)
+{
+       raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
+}
+
+static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
+{
+       struct its_vlpi_map *map = get_vlpi_map(d);
+       int cpu;
+
+       if (map) {
+               cpu = vpe_to_cpuid_lock(map->vpe, flags);
+       } else {
+               /* Physical LPIs are already locked via the irq_desc lock */
+               struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+               cpu = its_dev->event_map.col_map[its_get_event_id(d)];
+               /* Keep GCC quiet... */
+               *flags = 0;
+       }
+
+       return cpu;
+}
+
+static void irq_to_cpuid_unlock(struct irq_data *d, unsigned long flags)
 {
-       struct its_device *its_dev = irq_data_get_irq_chip_data(d);
        struct its_vlpi_map *map = get_vlpi_map(d);
 
        if (map)
-               return map->vpe->col_idx;
-
-       return its_dev->event_map.col_map[its_get_event_id(d)];
+               vpe_to_cpuid_unlock(map->vpe, flags);
 }
 
 static struct its_collection *valid_col(struct its_collection *col)
@@ -353,6 +389,15 @@ struct its_cmd_desc {
                struct {
                        struct its_vpe *vpe;
                } its_invdb_cmd;
+
+               struct {
+                       struct its_vpe *vpe;
+                       u8 sgi;
+                       u8 priority;
+                       bool enable;
+                       bool group;
+                       bool clear;
+               } its_vsgi_cmd;
        };
 };
 
@@ -501,6 +546,31 @@ static void its_encode_db(struct its_cmd_block *cmd, bool db)
        its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
 }
 
+static void its_encode_sgi_intid(struct its_cmd_block *cmd, u8 sgi)
+{
+       its_mask_encode(&cmd->raw_cmd[0], sgi, 35, 32);
+}
+
+static void its_encode_sgi_priority(struct its_cmd_block *cmd, u8 prio)
+{
+       its_mask_encode(&cmd->raw_cmd[0], prio >> 4, 23, 20);
+}
+
+static void its_encode_sgi_group(struct its_cmd_block *cmd, bool grp)
+{
+       its_mask_encode(&cmd->raw_cmd[0], grp, 10, 10);
+}
+
+static void its_encode_sgi_clear(struct its_cmd_block *cmd, bool clr)
+{
+       its_mask_encode(&cmd->raw_cmd[0], clr, 9, 9);
+}
+
+static void its_encode_sgi_enable(struct its_cmd_block *cmd, bool en)
+{
+       its_mask_encode(&cmd->raw_cmd[0], en, 8, 8);
+}
+
 static inline void its_fixup_cmd(struct its_cmd_block *cmd)
 {
        /* Let's fixup BE commands */
@@ -866,6 +936,26 @@ static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
        return valid_vpe(its, desc->its_invdb_cmd.vpe);
 }
 
+static struct its_vpe *its_build_vsgi_cmd(struct its_node *its,
+                                         struct its_cmd_block *cmd,
+                                         struct its_cmd_desc *desc)
+{
+       if (WARN_ON(!is_v4_1(its)))
+               return NULL;
+
+       its_encode_cmd(cmd, GITS_CMD_VSGI);
+       its_encode_vpeid(cmd, desc->its_vsgi_cmd.vpe->vpe_id);
+       its_encode_sgi_intid(cmd, desc->its_vsgi_cmd.sgi);
+       its_encode_sgi_priority(cmd, desc->its_vsgi_cmd.priority);
+       its_encode_sgi_group(cmd, desc->its_vsgi_cmd.group);
+       its_encode_sgi_clear(cmd, desc->its_vsgi_cmd.clear);
+       its_encode_sgi_enable(cmd, desc->its_vsgi_cmd.enable);
+
+       its_fixup_cmd(cmd);
+
+       return valid_vpe(its, desc->its_vsgi_cmd.vpe);
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
                                 struct its_cmd_block *ptr)
 {
@@ -1214,7 +1304,7 @@ static void its_send_vmovp(struct its_vpe *vpe)
                if (!is_v4(its))
                        continue;
 
-               if (!vpe->its_vm->vlpi_count[its->list_nr])
+               if (!require_its_list_vmovp(vpe->its_vm, its))
                        continue;
 
                desc.its_vmovp_cmd.col = &its->collections[col_id];
@@ -1329,7 +1419,9 @@ static void direct_lpi_inv(struct irq_data *d)
 {
        struct its_vlpi_map *map = get_vlpi_map(d);
        void __iomem *rdbase;
+       unsigned long flags;
        u64 val;
+       int cpu;
 
        if (map) {
                struct its_device *its_dev = irq_data_get_irq_chip_data(d);
@@ -1344,10 +1436,14 @@ static void direct_lpi_inv(struct irq_data *d)
        }
 
        /* Target the redistributor this LPI is currently routed to */
-       rdbase = per_cpu_ptr(gic_rdists->rdist, irq_to_cpuid(d))->rd_base;
+       cpu = irq_to_cpuid_lock(d, &flags);
+       raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
+       rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
        gic_write_lpir(val, rdbase + GICR_INVLPIR);
 
        wait_for_syncr(rdbase);
+       raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+       irq_to_cpuid_unlock(d, flags);
 }
 
 static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
@@ -1499,12 +1595,31 @@ static int its_irq_set_irqchip_state(struct irq_data *d,
        return 0;
 }
 
+/*
+ * Two favourable cases:
+ *
+ * (a) Either we have a GICv4.1, and all vPEs have to be mapped at all times
+ *     for vSGI delivery
+ *
+ * (b) Or the ITSs do not use a list map, meaning that VMOVP is cheap enough
+ *     and we're better off mapping all VPEs always
+ *
+ * If neither (a) nor (b) is true, then we map vPEs on demand.
+ *
+ */
+static bool gic_requires_eager_mapping(void)
+{
+       if (!its_list_map || gic_rdists->has_rvpeid)
+               return true;
+
+       return false;
+}
+
 static void its_map_vm(struct its_node *its, struct its_vm *vm)
 {
        unsigned long flags;
 
-       /* Not using the ITS list? Everything is always mapped. */
-       if (!its_list_map)
+       if (gic_requires_eager_mapping())
                return;
 
        raw_spin_lock_irqsave(&vmovp_lock, flags);
@@ -1538,7 +1653,7 @@ static void its_unmap_vm(struct its_node *its, struct its_vm *vm)
        unsigned long flags;
 
        /* Not using the ITS list? Everything is always mapped. */
-       if (!its_list_map)
+       if (gic_requires_eager_mapping())
                return;
 
        raw_spin_lock_irqsave(&vmovp_lock, flags);
@@ -2452,6 +2567,10 @@ static bool allocate_vpe_l2_table(int cpu, u32 id)
        if (!gic_rdists->has_rvpeid)
                return true;
 
+       /* Skip non-present CPUs */
+       if (!base)
+               return true;
+
        val  = gicr_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
 
        esz  = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val) + 1;
@@ -3482,17 +3601,25 @@ static int its_vpe_set_affinity(struct irq_data *d,
 {
        struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
        int from, cpu = cpumask_first(mask_val);
+       unsigned long flags;
 
        /*
         * Changing affinity is mega expensive, so let's be as lazy as
         * we can and only do it if we really have to. Also, if mapped
         * into the proxy device, we need to move the doorbell
         * interrupt to its new location.
+        *
+        * Another thing is that changing the affinity of a vPE affects
+        * *other interrupts* such as all the vLPIs that are routed to
+        * this vPE. This means that the irq_desc lock is not enough to
+        * protect us, and that we must ensure nobody samples vpe->col_idx
+        * during the update, hence the lock below which must also be
+        * taken on any vLPI handling path that evaluates vpe->col_idx.
         */
-       if (vpe->col_idx == cpu)
+       from = vpe_to_cpuid_lock(vpe, &flags);
+       if (from == cpu)
                goto out;
 
-       from = vpe->col_idx;
        vpe->col_idx = cpu;
 
        /*
@@ -3508,6 +3635,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
 
 out:
        irq_data_update_effective_affinity(d, cpumask_of(cpu));
+       vpe_to_cpuid_unlock(vpe, flags);
 
        return IRQ_SET_MASK_OK_DONE;
 }
@@ -3619,9 +3747,11 @@ static void its_vpe_send_inv(struct irq_data *d)
                void __iomem *rdbase;
 
                /* Target the redistributor this VPE is currently known on */
+               raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
                rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
                gic_write_lpir(d->parent_data->hwirq, rdbase + GICR_INVLPIR);
                wait_for_syncr(rdbase);
+               raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
        } else {
                its_vpe_send_cmd(vpe, its_send_inv);
        }
@@ -3782,8 +3912,12 @@ static void its_vpe_4_1_invall(struct its_vpe *vpe)
        val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
 
        /* Target the redistributor this vPE is currently known on */
+       raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
        rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
        gic_write_lpir(val, rdbase + GICR_INVALLR);
+
+       wait_for_syncr(rdbase);
+       raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
 }
 
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
@@ -3818,6 +3952,221 @@ static struct irq_chip its_vpe_4_1_irq_chip = {
        .irq_set_vcpu_affinity  = its_vpe_4_1_set_vcpu_affinity,
 };
 
+static void its_configure_sgi(struct irq_data *d, bool clear)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+       struct its_cmd_desc desc;
+
+       desc.its_vsgi_cmd.vpe = vpe;
+       desc.its_vsgi_cmd.sgi = d->hwirq;
+       desc.its_vsgi_cmd.priority = vpe->sgi_config[d->hwirq].priority;
+       desc.its_vsgi_cmd.enable = vpe->sgi_config[d->hwirq].enabled;
+       desc.its_vsgi_cmd.group = vpe->sgi_config[d->hwirq].group;
+       desc.its_vsgi_cmd.clear = clear;
+
+       /*
+        * GICv4.1 allows us to send VSGI commands to any ITS as long as the
+        * destination VPE is mapped there. Since we map them eagerly at
+        * activation time, we're pretty sure the first GICv4.1 ITS will do.
+        */
+       its_send_single_vcommand(find_4_1_its(), its_build_vsgi_cmd, &desc);
+}
+
+static void its_sgi_mask_irq(struct irq_data *d)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+       vpe->sgi_config[d->hwirq].enabled = false;
+       its_configure_sgi(d, false);
+}
+
+static void its_sgi_unmask_irq(struct irq_data *d)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+       vpe->sgi_config[d->hwirq].enabled = true;
+       its_configure_sgi(d, false);
+}
+
+static int its_sgi_set_affinity(struct irq_data *d,
+                               const struct cpumask *mask_val,
+                               bool force)
+{
+       /*
+        * There is no notion of affinity for virtual SGIs, at least
+        * not on the host (since they can only be targetting a vPE).
+        * Tell the kernel we've done whatever it asked for.
+        */
+       return IRQ_SET_MASK_OK;
+}
+
+static int its_sgi_set_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which,
+                                    bool state)
+{
+       if (which != IRQCHIP_STATE_PENDING)
+               return -EINVAL;
+
+       if (state) {
+               struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+               struct its_node *its = find_4_1_its();
+               u64 val;
+
+               val  = FIELD_PREP(GITS_SGIR_VPEID, vpe->vpe_id);
+               val |= FIELD_PREP(GITS_SGIR_VINTID, d->hwirq);
+               writeq_relaxed(val, its->sgir_base + GITS_SGIR - SZ_128K);
+       } else {
+               its_configure_sgi(d, true);
+       }
+
+       return 0;
+}
+
+static int its_sgi_get_irqchip_state(struct irq_data *d,
+                                    enum irqchip_irq_state which, bool *val)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+       void __iomem *base;
+       unsigned long flags;
+       u32 count = 1000000;    /* 1s! */
+       u32 status;
+       int cpu;
+
+       if (which != IRQCHIP_STATE_PENDING)
+               return -EINVAL;
+
+       /*
+        * Locking galore! We can race against two different events:
+        *
+        * - Concurent vPE affinity change: we must make sure it cannot
+        *   happen, or we'll talk to the wrong redistributor. This is
+        *   identical to what happens with vLPIs.
+        *
+        * - Concurrent VSGIPENDR access: As it involves accessing two
+        *   MMIO registers, this must be made atomic one way or another.
+        */
+       cpu = vpe_to_cpuid_lock(vpe, &flags);
+       raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
+       base = gic_data_rdist_cpu(cpu)->rd_base + SZ_128K;
+       writel_relaxed(vpe->vpe_id, base + GICR_VSGIR);
+       do {
+               status = readl_relaxed(base + GICR_VSGIPENDR);
+               if (!(status & GICR_VSGIPENDR_BUSY))
+                       goto out;
+
+               count--;
+               if (!count) {
+                       pr_err_ratelimited("Unable to get SGI status\n");
+                       goto out;
+               }
+               cpu_relax();
+               udelay(1);
+       } while (count);
+
+out:
+       raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+       vpe_to_cpuid_unlock(vpe, flags);
+
+       if (!count)
+               return -ENXIO;
+
+       *val = !!(status & (1 << d->hwirq));
+
+       return 0;
+}
+
+static int its_sgi_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+       struct its_cmd_info *info = vcpu_info;
+
+       switch (info->cmd_type) {
+       case PROP_UPDATE_VSGI:
+               vpe->sgi_config[d->hwirq].priority = info->priority;
+               vpe->sgi_config[d->hwirq].group = info->group;
+               its_configure_sgi(d, false);
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static struct irq_chip its_sgi_irq_chip = {
+       .name                   = "GICv4.1-sgi",
+       .irq_mask               = its_sgi_mask_irq,
+       .irq_unmask             = its_sgi_unmask_irq,
+       .irq_set_affinity       = its_sgi_set_affinity,
+       .irq_set_irqchip_state  = its_sgi_set_irqchip_state,
+       .irq_get_irqchip_state  = its_sgi_get_irqchip_state,
+       .irq_set_vcpu_affinity  = its_sgi_set_vcpu_affinity,
+};
+
+static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
+                                   unsigned int virq, unsigned int nr_irqs,
+                                   void *args)
+{
+       struct its_vpe *vpe = args;
+       int i;
+
+       /* Yes, we do want 16 SGIs */
+       WARN_ON(nr_irqs != 16);
+
+       for (i = 0; i < 16; i++) {
+               vpe->sgi_config[i].priority = 0;
+               vpe->sgi_config[i].enabled = false;
+               vpe->sgi_config[i].group = false;
+
+               irq_domain_set_hwirq_and_chip(domain, virq + i, i,
+                                             &its_sgi_irq_chip, vpe);
+               irq_set_status_flags(virq + i, IRQ_DISABLE_UNLAZY);
+       }
+
+       return 0;
+}
+
+static void its_sgi_irq_domain_free(struct irq_domain *domain,
+                                   unsigned int virq,
+                                   unsigned int nr_irqs)
+{
+       /* Nothing to do */
+}
+
+static int its_sgi_irq_domain_activate(struct irq_domain *domain,
+                                      struct irq_data *d, bool reserve)
+{
+       /* Write out the initial SGI configuration */
+       its_configure_sgi(d, false);
+       return 0;
+}
+
+static void its_sgi_irq_domain_deactivate(struct irq_domain *domain,
+                                         struct irq_data *d)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+       /*
+        * The VSGI command is awkward:
+        *
+        * - To change the configuration, CLEAR must be set to false,
+        *   leaving the pending bit unchanged.
+        * - To clear the pending bit, CLEAR must be set to true, leaving
+        *   the configuration unchanged.
+        *
+        * You just can't do both at once, hence the two commands below.
+        */
+       vpe->sgi_config[d->hwirq].enabled = false;
+       its_configure_sgi(d, false);
+       its_configure_sgi(d, true);
+}
+
+static const struct irq_domain_ops its_sgi_domain_ops = {
+       .alloc          = its_sgi_irq_domain_alloc,
+       .free           = its_sgi_irq_domain_free,
+       .activate       = its_sgi_irq_domain_activate,
+       .deactivate     = its_sgi_irq_domain_deactivate,
+};
+
 static int its_vpe_id_alloc(void)
 {
        return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
@@ -3851,6 +4200,7 @@ static int its_vpe_init(struct its_vpe *vpe)
                return -ENOMEM;
        }
 
+       raw_spin_lock_init(&vpe->vpe_lock);
        vpe->vpe_id = vpe_id;
        vpe->vpt_page = vpt_page;
        if (gic_rdists->has_rvpeid)
@@ -3960,8 +4310,12 @@ static int its_vpe_irq_domain_activate(struct irq_domain *domain,
        struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
        struct its_node *its;
 
-       /* If we use the list map, we issue VMAPP on demand... */
-       if (its_list_map)
+       /*
+        * If we use the list map, we issue VMAPP on demand... Unless
+        * we're on a GICv4.1 and we eagerly map the VPE on all ITSs
+        * so that VSGIs can work.
+        */
+       if (!gic_requires_eager_mapping())
                return 0;
 
        /* Map the VPE to the first possible CPU */
@@ -3987,10 +4341,10 @@ static void its_vpe_irq_domain_deactivate(struct irq_domain *domain,
        struct its_node *its;
 
        /*
-        * If we use the list map, we unmap the VPE once no VLPIs are
-        * associated with the VM.
+        * If we use the list map on GICv4.0, we unmap the VPE once no
+        * VLPIs are associated with the VM.
         */
-       if (its_list_map)
+       if (!gic_requires_eager_mapping())
                return;
 
        list_for_each_entry(its, &its_nodes, entry) {
@@ -4404,7 +4758,7 @@ static int __init its_probe_one(struct resource *res,
        struct page *page;
        int err;
 
-       its_base = ioremap(res->start, resource_size(res));
+       its_base = ioremap(res->start, SZ_64K);
        if (!its_base) {
                pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
                return -ENOMEM;
@@ -4455,6 +4809,13 @@ static int __init its_probe_one(struct resource *res,
 
                if (is_v4_1(its)) {
                        u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
+
+                       its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
+                       if (!its->sgir_base) {
+                               err = -ENOMEM;
+                               goto out_free_its;
+                       }
+
                        its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
 
                        pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
@@ -4468,7 +4829,7 @@ static int __init its_probe_one(struct resource *res,
                                get_order(ITS_CMD_QUEUE_SZ));
        if (!page) {
                err = -ENOMEM;
-               goto out_free_its;
+               goto out_unmap_sgir;
        }
        its->cmd_base = (void *)page_address(page);
        its->cmd_write = its->cmd_base;
@@ -4535,6 +4896,9 @@ out_free_tables:
        its_free_tables(its);
 out_free_cmd:
        free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ));
+out_unmap_sgir:
+       if (its->sgir_base)
+               iounmap(its->sgir_base);
 out_free_its:
        kfree(its);
 out_unmap:
@@ -4818,6 +5182,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
        struct device_node *of_node;
        struct its_node *its;
        bool has_v4 = false;
+       bool has_v4_1 = false;
        int err;
 
        gic_rdists = rdists;
@@ -4838,12 +5203,25 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
        if (err)
                return err;
 
-       list_for_each_entry(its, &its_nodes, entry)
+       list_for_each_entry(its, &its_nodes, entry) {
                has_v4 |= is_v4(its);
+               has_v4_1 |= is_v4_1(its);
+       }
+
+       /* Don't bother with inconsistent systems */
+       if (WARN_ON(!has_v4_1 && rdists->has_rvpeid))
+               rdists->has_rvpeid = false;
 
        if (has_v4 & rdists->has_vlpis) {
+               const struct irq_domain_ops *sgi_ops;
+
+               if (has_v4_1)
+                       sgi_ops = &its_sgi_domain_ops;
+               else
+                       sgi_ops = NULL;
+
                if (its_init_vpe_domain() ||
-                   its_init_v4(parent_domain, &its_vpe_domain_ops)) {
+                   its_init_v4(parent_domain, &its_vpe_domain_ops, sgi_ops)) {
                        rdists->has_vlpis = false;
                        pr_err("ITS: Disabling GICv4 support\n");
                }
index c1f7af9d9ae719a8b01cf7c84760ce6cd9781070..8c5de59c52135fde22b623dbd97e33a6394e3611 100644 (file)
@@ -723,6 +723,7 @@ static void __init gic_dist_init(void)
        unsigned int i;
        u64 affinity;
        void __iomem *base = gic_data.dist_base;
+       u32 val;
 
        /* Disable the distributor */
        writel_relaxed(0, base + GICD_CTLR);
@@ -755,9 +756,14 @@ static void __init gic_dist_init(void)
        /* Now do the common stuff, and wait for the distributor to drain */
        gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
 
+       val = GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1;
+       if (gic_data.rdists.gicd_typer2 & GICD_TYPER2_nASSGIcap) {
+               pr_info("Enabling SGIs without active state\n");
+               val |= GICD_CTLR_nASSGIreq;
+       }
+
        /* Enable distributor with ARE, Group1 */
-       writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
-                      base + GICD_CTLR);
+       writel_relaxed(val, base + GICD_CTLR);
 
        /*
         * Set all global interrupts to the boot CPU only. ARE must be
@@ -828,6 +834,7 @@ static int __gic_populate_rdist(struct redist_region *region, void __iomem *ptr)
        typer = gic_read_typer(ptr + GICR_TYPER);
        if ((typer >> 32) == aff) {
                u64 offset = ptr - region->redist_base;
+               raw_spin_lock_init(&gic_data_rdist()->rd_lock);
                gic_data_rdist_rd_base() = ptr;
                gic_data_rdist()->phys_base = region->phys_base + offset;
 
@@ -1757,6 +1764,7 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
                gic_v3_kvm_info.vcpu = r;
 
        gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
+       gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
        gic_set_kvm_info(&gic_v3_kvm_info);
 }
 
@@ -2072,6 +2080,7 @@ static void __init gic_acpi_setup_kvm_info(void)
        }
 
        gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
+       gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
        gic_set_kvm_info(&gic_v3_kvm_info);
 }
 
index 45969927cc811779faba3f2b00e3b934ec64c8f8..0c18714ae13ec6297945fbf721f0d102283cc5c8 100644 (file)
 
 static struct irq_domain *gic_domain;
 static const struct irq_domain_ops *vpe_domain_ops;
+static const struct irq_domain_ops *sgi_domain_ops;
+
+static bool has_v4_1(void)
+{
+       return !!sgi_domain_ops;
+}
+
+static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
+{
+       char *name;
+       int sgi_base;
+
+       if (!has_v4_1())
+               return 0;
+
+       name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current));
+       if (!name)
+               goto err;
+
+       vpe->fwnode = irq_domain_alloc_named_id_fwnode(name, idx);
+       if (!vpe->fwnode)
+               goto err;
+
+       kfree(name);
+       name = NULL;
+
+       vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16,
+                                                  sgi_domain_ops, vpe);
+       if (!vpe->sgi_domain)
+               goto err;
+
+       sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, 16,
+                                              NUMA_NO_NODE, vpe,
+                                              false, NULL);
+       if (sgi_base <= 0)
+               goto err;
+
+       return 0;
+
+err:
+       if (vpe->sgi_domain)
+               irq_domain_remove(vpe->sgi_domain);
+       if (vpe->fwnode)
+               irq_domain_free_fwnode(vpe->fwnode);
+       kfree(name);
+       return -ENOMEM;
+}
 
 int its_alloc_vcpu_irqs(struct its_vm *vm)
 {
@@ -112,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
        if (vpe_base_irq <= 0)
                goto err;
 
-       for (i = 0; i < vm->nr_vpes; i++)
+       for (i = 0; i < vm->nr_vpes; i++) {
+               int ret;
                vm->vpes[i]->irq = vpe_base_irq + i;
+               ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
+               if (ret)
+                       goto err;
+       }
 
        return 0;
 
@@ -126,8 +178,28 @@ err:
        return -ENOMEM;
 }
 
+static void its_free_sgi_irqs(struct its_vm *vm)
+{
+       int i;
+
+       if (!has_v4_1())
+               return;
+
+       for (i = 0; i < vm->nr_vpes; i++) {
+               unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
+
+               if (WARN_ON(!irq))
+                       continue;
+
+               irq_domain_free_irqs(irq, 16);
+               irq_domain_remove(vm->vpes[i]->sgi_domain);
+               irq_domain_free_fwnode(vm->vpes[i]->fwnode);
+       }
+}
+
 void its_free_vcpu_irqs(struct its_vm *vm)
 {
+       its_free_sgi_irqs(vm);
        irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
        irq_domain_remove(vm->domain);
        irq_domain_free_fwnode(vm->fwnode);
@@ -138,18 +210,50 @@ static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
        return irq_set_vcpu_affinity(vpe->irq, info);
 }
 
-int its_schedule_vpe(struct its_vpe *vpe, bool on)
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db)
+{
+       struct irq_desc *desc = irq_to_desc(vpe->irq);
+       struct its_cmd_info info = { };
+       int ret;
+
+       WARN_ON(preemptible());
+
+       info.cmd_type = DESCHEDULE_VPE;
+       if (has_v4_1()) {
+               /* GICv4.1 can directly deal with doorbells */
+               info.req_db = db;
+       } else {
+               /* Undo the nested disable_irq() calls... */
+               while (db && irqd_irq_disabled(&desc->irq_data))
+                       enable_irq(vpe->irq);
+       }
+
+       ret = its_send_vpe_cmd(vpe, &info);
+       if (!ret)
+               vpe->resident = false;
+
+       return ret;
+}
+
+int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en)
 {
-       struct its_cmd_info info;
+       struct its_cmd_info info = { };
        int ret;
 
        WARN_ON(preemptible());
 
-       info.cmd_type = on ? SCHEDULE_VPE : DESCHEDULE_VPE;
+       info.cmd_type = SCHEDULE_VPE;
+       if (has_v4_1()) {
+               info.g0en = g0en;
+               info.g1en = g1en;
+       } else {
+               /* Disabled the doorbell, as we're about to enter the guest */
+               disable_irq_nosync(vpe->irq);
+       }
 
        ret = its_send_vpe_cmd(vpe, &info);
        if (!ret)
-               vpe->resident = on;
+               vpe->resident = true;
 
        return ret;
 }
@@ -216,12 +320,28 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
        return irq_set_vcpu_affinity(irq, &info);
 }
 
-int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops)
+int its_prop_update_vsgi(int irq, u8 priority, bool group)
+{
+       struct its_cmd_info info = {
+               .cmd_type = PROP_UPDATE_VSGI,
+               {
+                       .priority       = priority,
+                       .group          = group,
+               },
+       };
+
+       return irq_set_vcpu_affinity(irq, &info);
+}
+
+int its_init_v4(struct irq_domain *domain,
+               const struct irq_domain_ops *vpe_ops,
+               const struct irq_domain_ops *sgi_ops)
 {
        if (domain) {
                pr_info("ITS: Enabling GICv4 support\n");
                gic_domain = domain;
-               vpe_domain_ops = ops;
+               vpe_domain_ops = vpe_ops;
+               sgi_domain_ops = sgi_ops;
                return 0;
        }
 
index 8c744578122a3e229079571b7bce093380c90662..a0d87ed9da69612224903eb192da987e3d5f5504 100644 (file)
@@ -300,9 +300,11 @@ static int control_loop(void *dummy)
 /*     i2c probing and setup                                           */
 /************************************************************************/
 
-static int
-do_attach( struct i2c_adapter *adapter )
+static void do_attach(struct i2c_adapter *adapter)
 {
+       struct i2c_board_info info = { };
+       struct device_node *np;
+
        /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
        static const unsigned short scan_ds1775[] = {
                0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
@@ -313,25 +315,24 @@ do_attach( struct i2c_adapter *adapter )
                I2C_CLIENT_END
        };
 
-       if( strncmp(adapter->name, "uni-n", 5) )
-               return 0;
-
-       if( !x.running ) {
-               struct i2c_board_info info;
+       if (x.running || strncmp(adapter->name, "uni-n", 5))
+               return;
 
-               memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+       np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,ds1775");
+       if (np) {
+               of_node_put(np);
+       } else {
+               strlcpy(info.type, "MAC,ds1775", I2C_NAME_SIZE);
                i2c_new_probed_device(adapter, &info, scan_ds1775, NULL);
+       }
 
-               strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+       np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,adm1030");
+       if (np) {
+               of_node_put(np);
+       } else {
+               strlcpy(info.type, "MAC,adm1030", I2C_NAME_SIZE);
                i2c_new_probed_device(adapter, &info, scan_adm1030, NULL);
-
-               if( x.thermostat && x.fan ) {
-                       x.running = 1;
-                       x.poll_task = kthread_run(control_loop, NULL, "g4fand");
-               }
        }
-       return 0;
 }
 
 static int
@@ -404,8 +405,8 @@ out:
 enum chip { ds1775, adm1030 };
 
 static const struct i2c_device_id therm_windtunnel_id[] = {
-       { "therm_ds1775", ds1775 },
-       { "therm_adm1030", adm1030 },
+       { "MAC,ds1775", ds1775 },
+       { "MAC,adm1030", adm1030 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, therm_windtunnel_id);
@@ -414,6 +415,7 @@ static int
 do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = cl->adapter;
+       int ret = 0;
 
        if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
                                     | I2C_FUNC_SMBUS_WRITE_BYTE) )
@@ -421,11 +423,19 @@ do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 
        switch (id->driver_data) {
        case adm1030:
-               return attach_fan( cl );
+               ret = attach_fan(cl);
+               break;
        case ds1775:
-               return attach_thermostat(cl);
+               ret = attach_thermostat(cl);
+               break;
        }
-       return 0;
+
+       if (!x.running && x.thermostat && x.fan) {
+               x.running = 1;
+               x.poll_task = kthread_run(control_loop, NULL, "g4fand");
+       }
+
+       return ret;
 }
 
 static struct i2c_driver g4fan_driver = {
index b155e95490761271262d46c4c46adface12c561a..b680b0caa69be91ab423391ea58e47724351e561 100644 (file)
@@ -598,7 +598,9 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
                        goto out;
                }
 
-               hdev->asic_funcs->halt_coresight(hdev);
+               if (!hdev->hard_reset_pending)
+                       hdev->asic_funcs->halt_coresight(hdev);
+
                hdev->in_debug = 0;
 
                goto out;
@@ -1189,6 +1191,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
        if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
                dev_info(hdev->dev,
                        "H/W state is dirty, must reset before initializing\n");
+               hdev->asic_funcs->halt_engines(hdev, true);
                hdev->asic_funcs->hw_fini(hdev, true);
        }
 
index 7344e8a222ae567fd3f525c242ce49a1750fe3ff..b8a8de24aaf722a3c2f4abee4f4720b616c9761b 100644 (file)
@@ -895,6 +895,11 @@ void goya_init_dma_qmans(struct hl_device *hdev)
  */
 static void goya_disable_external_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return;
+
        WREG32(mmDMA_QM_0_GLBL_CFG0, 0);
        WREG32(mmDMA_QM_1_GLBL_CFG0, 0);
        WREG32(mmDMA_QM_2_GLBL_CFG0, 0);
@@ -956,6 +961,11 @@ static int goya_stop_external_queues(struct hl_device *hdev)
 {
        int rc, retval = 0;
 
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return retval;
+
        rc = goya_stop_queue(hdev,
                        mmDMA_QM_0_GLBL_CFG1,
                        mmDMA_QM_0_CP_STS,
@@ -1744,9 +1754,18 @@ void goya_init_tpc_qmans(struct hl_device *hdev)
  */
 static void goya_disable_internal_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               goto disable_tpc;
+
        WREG32(mmMME_QM_GLBL_CFG0, 0);
        WREG32(mmMME_CMDQ_GLBL_CFG0, 0);
 
+disable_tpc:
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return;
+
        WREG32(mmTPC0_QM_GLBL_CFG0, 0);
        WREG32(mmTPC0_CMDQ_GLBL_CFG0, 0);
 
@@ -1782,8 +1801,12 @@ static void goya_disable_internal_queues(struct hl_device *hdev)
  */
 static int goya_stop_internal_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
        int rc, retval = 0;
 
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               goto stop_tpc;
+
        /*
         * Each queue (QMAN) is a separate H/W logic. That means that each
         * QMAN can be stopped independently and failure to stop one does NOT
@@ -1810,6 +1833,10 @@ static int goya_stop_internal_queues(struct hl_device *hdev)
                retval = -EIO;
        }
 
+stop_tpc:
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return retval;
+
        rc = goya_stop_queue(hdev,
                        mmTPC0_QM_GLBL_CFG1,
                        mmTPC0_QM_CP_STS,
@@ -1975,6 +2002,11 @@ static int goya_stop_internal_queues(struct hl_device *hdev)
 
 static void goya_dma_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return;
+
        WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
        WREG32(mmDMA_QM_1_GLBL_CFG1, 1 << DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT);
        WREG32(mmDMA_QM_2_GLBL_CFG1, 1 << DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT);
@@ -1984,6 +2016,11 @@ static void goya_dma_stall(struct hl_device *hdev)
 
 static void goya_tpc_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return;
+
        WREG32(mmTPC0_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT);
        WREG32(mmTPC1_CFG_TPC_STALL, 1 << TPC1_CFG_TPC_STALL_V_SHIFT);
        WREG32(mmTPC2_CFG_TPC_STALL, 1 << TPC2_CFG_TPC_STALL_V_SHIFT);
@@ -1996,6 +2033,11 @@ static void goya_tpc_stall(struct hl_device *hdev)
 
 static void goya_mme_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               return;
+
        WREG32(mmMME_STALL, 0xFFFFFFFF);
 }
 
@@ -4648,8 +4690,6 @@ static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size,
 
        rc = goya_send_job_on_qman0(hdev, job);
 
-       hl_cb_put(job->patched_cb);
-
        hl_debugfs_remove_job(hdev, job);
        kfree(job);
        cb->cs_cnt--;
index 48d5ec770b94242fddb71a02effab6fc1ee988e8..d10805e5e6232b91bf8e125e2734da4629712b1b 100644 (file)
@@ -3526,6 +3526,47 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
        }
 }
 
+#ifdef CONFIG_LOCKDEP
+static int bond_get_lowest_level_rcu(struct net_device *dev)
+{
+       struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int cur = 0, max = 0;
+
+       now = dev;
+       iter = &dev->adj_list.lower;
+
+       while (1) {
+               next = NULL;
+               while (1) {
+                       ldev = netdev_next_lower_dev_rcu(now, &iter);
+                       if (!ldev)
+                               break;
+
+                       next = ldev;
+                       niter = &ldev->adj_list.lower;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       if (max <= cur)
+                               max = cur;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return max;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
+       }
+
+       return max;
+}
+#endif
+
 static void bond_get_stats(struct net_device *bond_dev,
                           struct rtnl_link_stats64 *stats)
 {
@@ -3533,11 +3574,17 @@ static void bond_get_stats(struct net_device *bond_dev,
        struct rtnl_link_stats64 temp;
        struct list_head *iter;
        struct slave *slave;
+       int nest_level = 0;
 
-       spin_lock(&bond->stats_lock);
-       memcpy(stats, &bond->bond_stats, sizeof(*stats));
 
        rcu_read_lock();
+#ifdef CONFIG_LOCKDEP
+       nest_level = bond_get_lowest_level_rcu(bond_dev);
+#endif
+
+       spin_lock_nested(&bond->stats_lock, nest_level);
+       memcpy(stats, &bond->bond_stats, sizeof(*stats));
+
        bond_for_each_slave_rcu(bond, slave, iter) {
                const struct rtnl_link_stats64 *new =
                        dev_get_stats(slave->dev, &temp);
@@ -3547,10 +3594,10 @@ static void bond_get_stats(struct net_device *bond_dev,
                /* save off the slave stats for the next run */
                memcpy(&slave->slave_stats, new, sizeof(*new));
        }
-       rcu_read_unlock();
 
        memcpy(&bond->bond_stats, stats, sizeof(*stats));
        spin_unlock(&bond->stats_lock);
+       rcu_read_unlock();
 }
 
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
@@ -3640,6 +3687,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
        case BOND_RELEASE_OLD:
        case SIOCBONDRELEASE:
                res = bond_release(bond_dev, slave_dev);
+               if (!res)
+                       netdev_update_lockdep_key(slave_dev);
                break;
        case BOND_SETHWADDR_OLD:
        case SIOCBONDSETHWADDR:
index ddb3916d3506bec2fe317973054a32ea5c4255ad..215c1092328937a01531840ea9222fc5fe0e13a2 100644 (file)
@@ -1398,6 +1398,8 @@ static int bond_option_slaves_set(struct bonding *bond,
        case '-':
                slave_dbg(bond->dev, dev, "Releasing interface\n");
                ret = bond_release(bond->dev, dev);
+               if (!ret)
+                       netdev_update_lockdep_key(dev);
                break;
 
        default:
index 449a22172e079649940a1c3ba76cd30fb6e46ccb..1a69286daa8d8adcc2b2e535c1bd4a02b380a1c0 100644 (file)
@@ -1366,6 +1366,9 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
 
                b53_get_vlan_entry(dev, vid, vl);
 
+               if (vid == 0 && vid == b53_default_pvid(dev))
+                       untagged = true;
+
                vl->members |= BIT(port);
                if (untagged && !dsa_is_cpu_port(ds, port))
                        vl->untag |= BIT(port);
index d1955543acd1d1d151d8292c9638c25de2267ae0..b0f5280a83cb612a1a5cfd62060b189b98a967e3 100644 (file)
@@ -69,8 +69,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
                /* Force link status for IMP port */
                reg = core_readl(priv, offset);
                reg |= (MII_SW_OR | LINK_STS);
-               if (priv->type == BCM7278_DEVICE_ID)
-                       reg |= GMII_SPEED_UP_2G;
+               reg &= ~GMII_SPEED_UP_2G;
                core_writel(priv, reg, offset);
 
                /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
index b016cc205f81f02c1c27a43a5f7618770c7a15ae..ca3a7a7a73c32700bde1206c3122f967edc58842 100644 (file)
@@ -278,13 +278,13 @@ int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip,
        switch (direction) {
        case MV88E6XXX_EGRESS_DIR_INGRESS:
                dest_port_chip = &chip->ingress_dest_port;
-               reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK;
+               reg &= ~MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK;
                reg |= port <<
                       __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK);
                break;
        case MV88E6XXX_EGRESS_DIR_EGRESS:
                dest_port_chip = &chip->egress_dest_port;
-               reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK;
+               reg &= ~MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK;
                reg |= port <<
                       __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
                break;
index a1f99bef4a683286bda9c141f9fed6e7953b68b0..7b55633d2cb939d23f08cb442e380cc215464115 100644 (file)
@@ -722,6 +722,11 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
        if (flags & ~AQ_PRIV_FLAGS_MASK)
                return -EOPNOTSUPP;
 
+       if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
+               netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
+               return -EINVAL;
+       }
+
        cfg->priv_flags = flags;
 
        if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
index 6102251bb909b02c3736b9e0f6f204b40eeba286..03ff92bc4a7fb11c97e4e128609ada081b0dfb44 100644 (file)
@@ -163,7 +163,7 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
        }
 
        if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-           (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci),
+           (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK,
                       aq_nic->active_vlans))) {
                netdev_err(aq_nic->ndev,
                           "ethtool: unknown vlan-id specified");
index cc70c606b6ef292fa61cd915942ee88f9ac40091..251767c31f7e59e47250ea96a5a1d1d4cfa1f056 100644 (file)
@@ -337,6 +337,8 @@ struct aq_fw_ops {
 
        void (*enable_ptp)(struct aq_hw_s *self, int enable);
 
+       void (*adjust_ptp)(struct aq_hw_s *self, uint64_t adj);
+
        int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);
 
        int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
index c85e3e29012c0be813dde299aa8731653362a791..e95f6a6bef733d1f944af19b852e18971795c21c 100644 (file)
@@ -533,8 +533,10 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
                                     dx_buff->len,
                                     DMA_TO_DEVICE);
 
-       if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa)))
+       if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) {
+               ret = 0;
                goto exit;
+       }
 
        first = dx_buff;
        dx_buff->len_pkt = skb->len;
@@ -655,10 +657,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
        if (likely(frags)) {
                err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw,
                                                       ring, frags);
-               if (err >= 0) {
-                       ++ring->stats.tx.packets;
-                       ring->stats.tx.bytes += skb->len;
-               }
        } else {
                err = NETDEV_TX_BUSY;
        }
index 6b27af0db4992888ec1d2648ef6b51f5c89aabc3..78b6f32487565f30069c12565d92dd73c182c9de 100644 (file)
@@ -359,7 +359,8 @@ static int aq_suspend_common(struct device *dev, bool deep)
        netif_device_detach(nic->ndev);
        netif_tx_stop_all_queues(nic->ndev);
 
-       aq_nic_stop(nic);
+       if (netif_running(nic->ndev))
+               aq_nic_stop(nic);
 
        if (deep) {
                aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol);
@@ -375,7 +376,7 @@ static int atl_resume_common(struct device *dev, bool deep)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct aq_nic_s *nic;
-       int ret;
+       int ret = 0;
 
        nic = pci_get_drvdata(pdev);
 
@@ -390,9 +391,11 @@ static int atl_resume_common(struct device *dev, bool deep)
                        goto err_exit;
        }
 
-       ret = aq_nic_start(nic);
-       if (ret)
-               goto err_exit;
+       if (netif_running(nic->ndev)) {
+               ret = aq_nic_start(nic);
+               if (ret)
+                       goto err_exit;
+       }
 
        netif_device_attach(nic->ndev);
        netif_tx_start_all_queues(nic->ndev);
index 951d86f8b66e8c9114510d41436c030cf7bffeb8..bae95a61856081afc83e36c43fd1b1bc59634d7a 100644 (file)
@@ -272,9 +272,12 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)
                        }
                }
 
-               if (unlikely(buff->is_eop))
-                       dev_kfree_skb_any(buff->skb);
+               if (unlikely(buff->is_eop)) {
+                       ++self->stats.rx.packets;
+                       self->stats.tx.bytes += buff->skb->len;
 
+                       dev_kfree_skb_any(buff->skb);
+               }
                buff->pa = 0U;
                buff->eop_index = 0xffffU;
                self->sw_head = aq_ring_next_dx(self, self->sw_head);
@@ -351,7 +354,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
                                err = 0;
                                goto err_exit;
                        }
-                       if (buff->is_error || buff->is_cso_err) {
+                       if (buff->is_error ||
+                           (buff->is_lro && buff->is_cso_err)) {
                                buff_ = buff;
                                do {
                                        next_ = buff_->next,
index 991e4d31b0948e86e21299c069d3bc70a738b3b0..2c96f20f62891dbec2184039cce3a7de952a6b14 100644 (file)
@@ -78,7 +78,8 @@ struct __packed aq_ring_buff_s {
                        u32 is_cleaned:1;
                        u32 is_error:1;
                        u32 is_vlan:1;
-                       u32 rsvd3:4;
+                       u32 is_lro:1;
+                       u32 rsvd3:3;
                        u16 eop_index;
                        u16 rsvd4;
                };
index ec041f78d0634426d76e23a23678c6be8321a69b..d20d91cdece861adeb0b45c44a69a8140cb048e4 100644 (file)
@@ -823,6 +823,8 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
                        }
                }
 
+               buff->is_lro = !!(HW_ATL_B0_RXD_WB_STAT2_RSCCNT &
+                                 rxd_wb->status);
                if (HW_ATL_B0_RXD_WB_STAT2_EOP & rxd_wb->status) {
                        buff->len = rxd_wb->pkt_len %
                                AQ_CFG_RX_FRAME_MAX;
@@ -835,8 +837,7 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
                                rxd_wb->pkt_len > AQ_CFG_RX_FRAME_MAX ?
                                AQ_CFG_RX_FRAME_MAX : rxd_wb->pkt_len;
 
-                       if (HW_ATL_B0_RXD_WB_STAT2_RSCCNT &
-                               rxd_wb->status) {
+                       if (buff->is_lro) {
                                /* LRO */
                                buff->next = rxd_wb->next_desc_ptr;
                                ++ring->stats.rx.lro_packets;
@@ -884,13 +885,16 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
 {
        struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
        unsigned int i = 0U;
+       u32 vlan_promisc;
+       u32 l2_promisc;
 
-       hw_atl_rpfl2promiscuous_mode_en_set(self,
-                                           IS_FILTER_ENABLED(IFF_PROMISC));
+       l2_promisc = IS_FILTER_ENABLED(IFF_PROMISC) ||
+                    !!(cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET));
+       vlan_promisc = l2_promisc || cfg->is_vlan_force_promisc;
 
-       hw_atl_rpf_vlan_prom_mode_en_set(self,
-                                    IS_FILTER_ENABLED(IFF_PROMISC) ||
-                                    cfg->is_vlan_force_promisc);
+       hw_atl_rpfl2promiscuous_mode_en_set(self, l2_promisc);
+
+       hw_atl_rpf_vlan_prom_mode_en_set(self, vlan_promisc);
 
        hw_atl_rpfl2multicast_flr_en_set(self,
                                         IS_FILTER_ENABLED(IFF_ALLMULTI) &&
@@ -1161,6 +1165,8 @@ static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta)
 {
        self->ptp_clk_offset += delta;
 
+       self->aq_fw_ops->adjust_ptp(self, self->ptp_clk_offset);
+
        return 0;
 }
 
@@ -1211,7 +1217,7 @@ static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index,
        fwreq.ptp_gpio_ctrl.index = index;
        fwreq.ptp_gpio_ctrl.period = period;
        /* Apply time offset */
-       fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset;
+       fwreq.ptp_gpio_ctrl.start = start;
 
        size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl);
        return self->aq_fw_ops->send_fw_request(self, &fwreq, size);
index f547baa6c95499e5f16313ea47b2c04f18f105ca..354705f9bc493afcbe9c63f28cc36f779eea4be5 100644 (file)
@@ -22,6 +22,7 @@
 #define HW_ATL_MIF_ADDR         0x0208U
 #define HW_ATL_MIF_VAL          0x020CU
 
+#define HW_ATL_MPI_RPC_ADDR     0x0334U
 #define HW_ATL_RPC_CONTROL_ADR  0x0338U
 #define HW_ATL_RPC_STATE_ADR    0x033CU
 
@@ -53,15 +54,14 @@ enum mcp_area {
 };
 
 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
-
 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
                                      enum hal_atl_utils_fw_state_e state);
-
 static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
 static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self);
 
 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
 {
@@ -476,6 +476,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
                                        self, self->mbox_addr,
                                        self->mbox_addr != 0U,
                                        1000U, 10000U);
+       err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self,
+                                       self->rpc_addr,
+                                       self->rpc_addr != 0U,
+                                       1000U, 100000U);
 
        return err;
 }
@@ -531,6 +535,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
                                                self, fw.val,
                                                sw.tid == fw.tid,
                                                1000U, 100000U);
+               if (err < 0)
+                       goto err_exit;
+
+               err = aq_hw_err_from_flags(self);
+               if (err < 0)
+                       goto err_exit;
 
                if (fw.len == 0xFFFFU) {
                        err = hw_atl_utils_fw_rpc_call(self, sw.len);
@@ -1025,6 +1035,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
        return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
 }
 
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self)
+{
+       return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR);
+}
+
 const struct aq_fw_ops aq_fw_1x_ops = {
        .init = hw_atl_utils_mpi_create,
        .deinit = hw_atl_fw1x_deinit,
index 97ebf849695fdb0b9cc386c535b3ff34e7fba3c4..77a4ed64830fd1e1c04814f1b18aecf99f0f0dd3 100644 (file)
@@ -30,6 +30,9 @@
 #define HW_ATL_FW3X_EXT_CONTROL_ADDR     0x378
 #define HW_ATL_FW3X_EXT_STATE_ADDR       0x37c
 
+#define HW_ATL_FW3X_PTP_ADJ_LSW_ADDR    0x50a0
+#define HW_ATL_FW3X_PTP_ADJ_MSW_ADDR    0x50a4
+
 #define HW_ATL_FW2X_CAP_PAUSE            BIT(CAPS_HI_PAUSE)
 #define HW_ATL_FW2X_CAP_ASYM_PAUSE       BIT(CAPS_HI_ASYMMETRIC_PAUSE)
 #define HW_ATL_FW2X_CAP_SLEEP_PROXY      BIT(CAPS_HI_SLEEP_PROXY)
@@ -475,6 +478,14 @@ static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable)
        aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts);
 }
 
+static void aq_fw3x_adjust_ptp(struct aq_hw_s *self, uint64_t adj)
+{
+       aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_LSW_ADDR,
+                       (adj >>  0) & 0xffffffff);
+       aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_MSW_ADDR,
+                       (adj >> 32) & 0xffffffff);
+}
+
 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
 {
        if (self->fw_ver_actual < HW_ATL_FW_VER_LED)
@@ -633,4 +644,5 @@ const struct aq_fw_ops aq_fw_2x_ops = {
        .enable_ptp         = aq_fw3x_enable_ptp,
        .led_control        = aq_fw2x_led_control,
        .set_phyloopback    = aq_fw2x_set_phyloopback,
+       .adjust_ptp         = aq_fw3x_adjust_ptp,
 };
index 597e6fd5bfea8344d21efc5da7918b3291ba3601..f9a8151f092c726dc553ec60459c6ba941e4a6e6 100644 (file)
@@ -11252,7 +11252,7 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp)
                }
        }
        if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
-               netdev_info(bp->dev, "Receive PF driver unload event!");
+               netdev_info(bp->dev, "Receive PF driver unload event!\n");
 }
 
 #else
@@ -11759,7 +11759,7 @@ static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[])
        u32 dw;
 
        if (!pos) {
-               netdev_info(bp->dev, "Unable do read adapter's DSN");
+               netdev_info(bp->dev, "Unable do read adapter's DSN\n");
                return -EOPNOTSUPP;
        }
 
@@ -11786,6 +11786,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (version_printed++ == 0)
                pr_info("%s", version);
 
+       /* Clear any pending DMA transactions from crash kernel
+        * while loading driver in capture kernel.
+        */
+       if (is_kdump_kernel()) {
+               pci_clear_master(pdev);
+               pcie_flr(pdev);
+       }
+
        max_irqs = bnxt_get_max_irq(pdev);
        dev = alloc_etherdev_mq(sizeof(*bp), max_irqs);
        if (!dev)
@@ -11983,10 +11991,10 @@ static void bnxt_shutdown(struct pci_dev *pdev)
                dev_close(dev);
 
        bnxt_ulp_shutdown(bp);
+       bnxt_clear_int_mode(bp);
+       pci_disable_device(pdev);
 
        if (system_state == SYSTEM_POWER_OFF) {
-               bnxt_clear_int_mode(bp);
-               pci_disable_device(pdev);
                pci_wake_from_d3(pdev, bp->wol);
                pci_set_power_state(pdev, PCI_D3hot);
        }
index eec0168330b757af7e598f1608342c2161bfbc2e..d3c93ccee86ad9570cbfbdc3762b47a7ff903a26 100644 (file)
@@ -641,14 +641,14 @@ static int bnxt_dl_params_register(struct bnxt *bp)
        rc = devlink_params_register(bp->dl, bnxt_dl_params,
                                     ARRAY_SIZE(bnxt_dl_params));
        if (rc) {
-               netdev_warn(bp->dev, "devlink_params_register failed. rc=%d",
+               netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
                            rc);
                return rc;
        }
        rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
                                          ARRAY_SIZE(bnxt_dl_port_params));
        if (rc) {
-               netdev_err(bp->dev, "devlink_port_params_register failed");
+               netdev_err(bp->dev, "devlink_port_params_register failed\n");
                devlink_params_unregister(bp->dl, bnxt_dl_params,
                                          ARRAY_SIZE(bnxt_dl_params));
                return rc;
@@ -679,7 +679,7 @@ int bnxt_dl_register(struct bnxt *bp)
        else
                dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
        if (!dl) {
-               netdev_warn(bp->dev, "devlink_alloc failed");
+               netdev_warn(bp->dev, "devlink_alloc failed\n");
                return -ENOMEM;
        }
 
@@ -692,7 +692,7 @@ int bnxt_dl_register(struct bnxt *bp)
 
        rc = devlink_register(dl, &bp->pdev->dev);
        if (rc) {
-               netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
+               netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc);
                goto err_dl_free;
        }
 
@@ -704,7 +704,7 @@ int bnxt_dl_register(struct bnxt *bp)
                               sizeof(bp->dsn));
        rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
        if (rc) {
-               netdev_err(bp->dev, "devlink_port_register failed");
+               netdev_err(bp->dev, "devlink_port_register failed\n");
                goto err_dl_unreg;
        }
 
index 6171fa8b3677b4097d3a10278dced2693b5a340b..e8fc1671c5815e761f80f70a80cd911c115e80ae 100644 (file)
@@ -2028,7 +2028,7 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
        }
 
        if (fw->size > item_len) {
-               netdev_err(dev, "PKG insufficient update area in nvram: %lu",
+               netdev_err(dev, "PKG insufficient update area in nvram: %lu\n",
                           (unsigned long)fw->size);
                rc = -EFBIG;
        } else {
@@ -3338,7 +3338,7 @@ err:
        kfree(coredump.data);
        *dump_len += sizeof(struct bnxt_coredump_record);
        if (rc == -ENOBUFS)
-               netdev_err(bp->dev, "Firmware returned large coredump buffer");
+               netdev_err(bp->dev, "Firmware returned large coredump buffer\n");
        return rc;
 }
 
index 0cc6ec51f45fe2ab028bb3c0299dbef0fd3bf088..9bec256b0934afd7285a45432d3fc461246216cb 100644 (file)
@@ -50,7 +50,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev)
 
        /* check if dev belongs to the same switch */
        if (!netdev_port_same_parent_id(pf_bp->dev, dev)) {
-               netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch",
+               netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch\n",
                            dev->ifindex);
                return BNXT_FID_INVALID;
        }
@@ -70,7 +70,7 @@ static int bnxt_tc_parse_redir(struct bnxt *bp,
        struct net_device *dev = act->dev;
 
        if (!dev) {
-               netdev_info(bp->dev, "no dev in mirred action");
+               netdev_info(bp->dev, "no dev in mirred action\n");
                return -EINVAL;
        }
 
@@ -106,7 +106,7 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
        const struct ip_tunnel_key *tun_key = &tun_info->key;
 
        if (ip_tunnel_info_af(tun_info) != AF_INET) {
-               netdev_info(bp->dev, "only IPv4 tunnel-encap is supported");
+               netdev_info(bp->dev, "only IPv4 tunnel-encap is supported\n");
                return -EOPNOTSUPP;
        }
 
@@ -295,7 +295,7 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
        int i, rc;
 
        if (!flow_action_has_entries(flow_action)) {
-               netdev_info(bp->dev, "no actions");
+               netdev_info(bp->dev, "no actions\n");
                return -EINVAL;
        }
 
@@ -370,7 +370,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
        /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
        if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
            (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
-               netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x",
+               netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x\n",
                            dissector->used_keys);
                return -EOPNOTSUPP;
        }
@@ -508,7 +508,7 @@ static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -841,7 +841,7 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp,
                resp = bnxt_get_hwrm_resp_addr(bp, &req);
                *decap_filter_handle = resp->decap_filter_id;
        } else {
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -859,7 +859,7 @@ static int hwrm_cfa_decap_filter_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -906,7 +906,7 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp,
                resp = bnxt_get_hwrm_resp_addr(bp, &req);
                *encap_record_handle = resp->encap_record_id;
        } else {
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -924,7 +924,7 @@ static int hwrm_cfa_encap_record_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -943,7 +943,7 @@ static int bnxt_tc_put_l2_node(struct bnxt *bp,
                                             tc_info->l2_ht_params);
                if (rc)
                        netdev_err(bp->dev,
-                                  "Error: %s: rhashtable_remove_fast: %d",
+                                  "Error: %s: rhashtable_remove_fast: %d\n",
                                   __func__, rc);
                kfree_rcu(l2_node, rcu);
        }
@@ -972,7 +972,7 @@ bnxt_tc_get_l2_node(struct bnxt *bp, struct rhashtable *l2_table,
                if (rc) {
                        kfree_rcu(l2_node, rcu);
                        netdev_err(bp->dev,
-                                  "Error: %s: rhashtable_insert_fast: %d",
+                                  "Error: %s: rhashtable_insert_fast: %d\n",
                                   __func__, rc);
                        return NULL;
                }
@@ -1031,7 +1031,7 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow)
        if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) &&
            (flow->l4_key.ip_proto != IPPROTO_TCP &&
             flow->l4_key.ip_proto != IPPROTO_UDP)) {
-               netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports",
+               netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports\n",
                            flow->l4_key.ip_proto);
                return false;
        }
@@ -1088,7 +1088,7 @@ static int bnxt_tc_put_tunnel_node(struct bnxt *bp,
                rc =  rhashtable_remove_fast(tunnel_table, &tunnel_node->node,
                                             *ht_params);
                if (rc) {
-                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
+                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
                        rc = -1;
                }
                kfree_rcu(tunnel_node, rcu);
@@ -1129,7 +1129,7 @@ bnxt_tc_get_tunnel_node(struct bnxt *bp, struct rhashtable *tunnel_table,
        tunnel_node->refcount++;
        return tunnel_node;
 err:
-       netdev_info(bp->dev, "error rc=%d", rc);
+       netdev_info(bp->dev, "error rc=%d\n", rc);
        return NULL;
 }
 
@@ -1187,7 +1187,7 @@ static void bnxt_tc_put_decap_l2_node(struct bnxt *bp,
                                             &decap_l2_node->node,
                                             tc_info->decap_l2_ht_params);
                if (rc)
-                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
+                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
                kfree_rcu(decap_l2_node, rcu);
        }
 }
@@ -1227,7 +1227,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
        rt = ip_route_output_key(dev_net(real_dst_dev), &flow);
        if (IS_ERR(rt)) {
-               netdev_info(bp->dev, "no route to %pI4b", &flow.daddr);
+               netdev_info(bp->dev, "no route to %pI4b\n", &flow.daddr);
                return -EOPNOTSUPP;
        }
 
@@ -1241,7 +1241,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
                if (vlan->real_dev != real_dst_dev) {
                        netdev_info(bp->dev,
-                                   "dst_dev(%s) doesn't use PF-if(%s)",
+                                   "dst_dev(%s) doesn't use PF-if(%s)\n",
                                    netdev_name(dst_dev),
                                    netdev_name(real_dst_dev));
                        rc = -EOPNOTSUPP;
@@ -1253,7 +1253,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 #endif
        } else if (dst_dev != real_dst_dev) {
                netdev_info(bp->dev,
-                           "dst_dev(%s) for %pI4b is not PF-if(%s)",
+                           "dst_dev(%s) for %pI4b is not PF-if(%s)\n",
                            netdev_name(dst_dev), &flow.daddr,
                            netdev_name(real_dst_dev));
                rc = -EOPNOTSUPP;
@@ -1262,7 +1262,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
        nbr = dst_neigh_lookup(&rt->dst, &flow.daddr);
        if (!nbr) {
-               netdev_info(bp->dev, "can't lookup neighbor for %pI4b",
+               netdev_info(bp->dev, "can't lookup neighbor for %pI4b\n",
                            &flow.daddr);
                rc = -EOPNOTSUPP;
                goto put_rt;
@@ -1472,7 +1472,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
        rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node,
                                    tc_info->flow_ht_params);
        if (rc)
-               netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d",
+               netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d\n",
                           __func__, rc);
 
        kfree_rcu(flow_node, rcu);
@@ -1587,7 +1587,7 @@ unlock:
 free_node:
        kfree_rcu(new_node, rcu);
 done:
-       netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d",
+       netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d\n",
                   __func__, tc_flow_cmd->cookie, rc);
        return rc;
 }
@@ -1700,7 +1700,7 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
                                                le64_to_cpu(resp_bytes[i]);
                }
        } else {
-               netdev_info(bp->dev, "error rc=%d", rc);
+               netdev_info(bp->dev, "error rc=%d\n", rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -1970,7 +1970,7 @@ static int bnxt_tc_indr_block_event(struct notifier_block *nb,
                                                   bp);
                if (rc)
                        netdev_info(bp->dev,
-                                   "Failed to register indirect blk: dev: %s",
+                                   "Failed to register indirect blk: dev: %s\n",
                                    netdev->name);
                break;
        case NETDEV_UNREGISTER:
index b010b34cdaf835fdf23eea5ffceaddce4386ec98..6f2faf81c1aead78822e81207c1213639971c248 100644 (file)
@@ -43,7 +43,7 @@ static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx,
                netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",
                           *tx_cfa_action, *rx_cfa_code);
        } else {
-               netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
        }
 
        mutex_unlock(&bp->hwrm_cmd_lock);
@@ -60,7 +60,7 @@ static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
        return rc;
 }
 
@@ -465,7 +465,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
        return 0;
 
 err:
-       netdev_info(bp->dev, "%s error=%d", __func__, rc);
+       netdev_info(bp->dev, "%s error=%d\n", __func__, rc);
        kfree(cfa_code_map);
        __bnxt_vf_reps_destroy(bp);
        return rc;
@@ -488,7 +488,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
 
        mutex_lock(&bp->sriov_lock);
        if (bp->eswitch_mode == mode) {
-               netdev_info(bp->dev, "already in %s eswitch mode",
+               netdev_info(bp->dev, "already in %s eswitch mode\n",
                            mode == DEVLINK_ESWITCH_MODE_LEGACY ?
                            "legacy" : "switchdev");
                rc = -EINVAL;
@@ -508,7 +508,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
                }
 
                if (pci_num_vf(bp->pdev) == 0) {
-                       netdev_info(bp->dev, "Enable VFs before setting switchdev mode");
+                       netdev_info(bp->dev, "Enable VFs before setting switchdev mode\n");
                        rc = -EPERM;
                        goto done;
                }
index b384997740717996485ed2ab6f8c882bba438d8d..99e2c6d4d8c3ad1cdd3f956851a99944789cb84c 100644 (file)
@@ -543,13 +543,13 @@ struct l4_kwq_update_pg {
 #define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
 #endif
 #if defined(__BIG_ENDIAN)
-       u16 reserverd3;
+       u16 reserved3;
        u8 da0;
        u8 da1;
 #elif defined(__LITTLE_ENDIAN)
        u8 da1;
        u8 da0;
-       u16 reserverd3;
+       u16 reserved3;
 #endif
 #if defined(__BIG_ENDIAN)
        u8 da2;
index 6392a25301838f849241dc53448db5b476b224f8..10244941a7a604fc51f2d3182034b4a93e681ee2 100644 (file)
@@ -294,6 +294,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
         */
        if (priv->ext_phy) {
                reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
+               reg &= ~ID_MODE_DIS;
                reg |= id_mode_dis;
                if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
                        reg |= RGMII_MODE_EN_V123;
index dbf7070fcdba26b66c54608d0e7f1bd673a3deae..a3f0f27fc79a1c3ebd6664afced137221eb257c0 100644 (file)
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH               0x00000080
 #define MACB_CAPS_NEEDS_RSTONUBR               0x00000100
+#define MACB_CAPS_MACB_IS_EMAC                 0x08000000
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
index 4508f0d150da95d8e838d0ead806e8ef74794cc5..2c28da1737fe4ec2c0d1579d71bb454a3cabe289 100644 (file)
@@ -572,8 +572,21 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
        old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);
 
        /* Clear all the bits we might set later */
-       ctrl &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE) |
-                 GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+       ctrl &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE));
+
+       if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
+               if (state->interface == PHY_INTERFACE_MODE_RMII)
+                       ctrl |= MACB_BIT(RM9200_RMII);
+       } else {
+               ctrl &= ~(GEM_BIT(GBE) | GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+
+               /* We do not support MLO_PAUSE_RX yet */
+               if (state->pause & MLO_PAUSE_TX)
+                       ctrl |= MACB_BIT(PAE);
+
+               if (state->interface == PHY_INTERFACE_MODE_SGMII)
+                       ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
+       }
 
        if (state->speed == SPEED_1000)
                ctrl |= GEM_BIT(GBE);
@@ -583,13 +596,6 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
        if (state->duplex)
                ctrl |= MACB_BIT(FD);
 
-       /* We do not support MLO_PAUSE_RX yet */
-       if (state->pause & MLO_PAUSE_TX)
-               ctrl |= MACB_BIT(PAE);
-
-       if (state->interface == PHY_INTERFACE_MODE_SGMII)
-               ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
-
        /* Apply the new configuration, if any */
        if (old_ctrl ^ ctrl)
                macb_or_gem_writel(bp, NCFGR, ctrl);
@@ -608,9 +614,10 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
        unsigned int q;
        u32 ctrl;
 
-       for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
-               queue_writel(queue, IDR,
-                            bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+       if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
+               for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
+                       queue_writel(queue, IDR,
+                                    bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
 
        /* Disable Rx and Tx */
        ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
@@ -627,17 +634,19 @@ static void macb_mac_link_up(struct phylink_config *config, unsigned int mode,
        struct macb_queue *queue;
        unsigned int q;
 
-       macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
+       if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
+               macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
 
-       /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
-        * cleared the pipeline and control registers.
-        */
-       bp->macbgem_ops.mog_init_rings(bp);
-       macb_init_buffers(bp);
+               /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
+                * cleared the pipeline and control registers.
+                */
+               bp->macbgem_ops.mog_init_rings(bp);
+               macb_init_buffers(bp);
 
-       for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
-               queue_writel(queue, IER,
-                            bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+               for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
+                       queue_writel(queue, IER,
+                                    bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+       }
 
        /* Enable Rx and Tx */
        macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
@@ -3790,6 +3799,10 @@ static int at91ether_open(struct net_device *dev)
        u32 ctl;
        int ret;
 
+       ret = pm_runtime_get_sync(&lp->pdev->dev);
+       if (ret < 0)
+               return ret;
+
        /* Clear internal statistics */
        ctl = macb_readl(lp, NCR);
        macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
@@ -3854,7 +3867,7 @@ static int at91ether_close(struct net_device *dev)
                          q->rx_buffers, q->rx_buffers_dma);
        q->rx_buffers = NULL;
 
-       return 0;
+       return pm_runtime_put(&lp->pdev->dev);
 }
 
 /* Transmit packet */
@@ -4037,7 +4050,6 @@ static int at91ether_init(struct platform_device *pdev)
        struct net_device *dev = platform_get_drvdata(pdev);
        struct macb *bp = netdev_priv(dev);
        int err;
-       u32 reg;
 
        bp->queues[0].bp = bp;
 
@@ -4051,11 +4063,7 @@ static int at91ether_init(struct platform_device *pdev)
 
        macb_writel(bp, NCR, 0);
 
-       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
-       if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
-               reg |= MACB_BIT(RM9200_RMII);
-
-       macb_writel(bp, NCFGR, reg);
+       macb_writel(bp, NCFGR, MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG));
 
        return 0;
 }
@@ -4214,7 +4222,7 @@ static const struct macb_config sama5d4_config = {
 };
 
 static const struct macb_config emac_config = {
-       .caps = MACB_CAPS_NEEDS_RSTONUBR,
+       .caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
        .clk_init = at91ether_clk_init,
        .init = at91ether_init,
 };
index 17a4110c2e4935d74e8f677ab0405fd73cec0593..8ff28ed04b7fcd0616760f91d727898d98f01f3e 100644 (file)
@@ -410,10 +410,19 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
        lmac = &bgx->lmac[lmacid];
 
        cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
-       if (enable)
+       if (enable) {
                cfg |= CMR_PKT_RX_EN | CMR_PKT_TX_EN;
-       else
+
+               /* enable TX FIFO Underflow interrupt */
+               bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1S,
+                              GMI_TXX_INT_UNDFLW);
+       } else {
                cfg &= ~(CMR_PKT_RX_EN | CMR_PKT_TX_EN);
+
+               /* Disable TX FIFO Underflow interrupt */
+               bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1C,
+                              GMI_TXX_INT_UNDFLW);
+       }
        bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
 
        if (bgx->is_rgx)
@@ -1535,6 +1544,48 @@ static int bgx_init_phy(struct bgx *bgx)
        return bgx_init_of_phy(bgx);
 }
 
+static irqreturn_t bgx_intr_handler(int irq, void *data)
+{
+       struct bgx *bgx = (struct bgx *)data;
+       u64 status, val;
+       int lmac;
+
+       for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
+               status = bgx_reg_read(bgx, lmac, BGX_GMP_GMI_TXX_INT);
+               if (status & GMI_TXX_INT_UNDFLW) {
+                       pci_err(bgx->pdev, "BGX%d lmac%d UNDFLW\n",
+                               bgx->bgx_id, lmac);
+                       val = bgx_reg_read(bgx, lmac, BGX_CMRX_CFG);
+                       val &= ~CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+                       val |= CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+               }
+               /* clear interrupts */
+               bgx_reg_write(bgx, lmac, BGX_GMP_GMI_TXX_INT, status);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void bgx_register_intr(struct pci_dev *pdev)
+{
+       struct bgx *bgx = pci_get_drvdata(pdev);
+       int ret;
+
+       ret = pci_alloc_irq_vectors(pdev, BGX_LMAC_VEC_OFFSET,
+                                   BGX_LMAC_VEC_OFFSET, PCI_IRQ_ALL_TYPES);
+       if (ret < 0) {
+               pci_err(pdev, "Req for #%d msix vectors failed\n",
+                       BGX_LMAC_VEC_OFFSET);
+               return;
+       }
+       ret = pci_request_irq(pdev, GMPX_GMI_TX_INT, bgx_intr_handler, NULL,
+                             bgx, "BGX%d", bgx->bgx_id);
+       if (ret)
+               pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+}
+
 static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err;
@@ -1550,7 +1601,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, bgx);
 
-       err = pci_enable_device(pdev);
+       err = pcim_enable_device(pdev);
        if (err) {
                dev_err(dev, "Failed to enable PCI device\n");
                pci_set_drvdata(pdev, NULL);
@@ -1604,6 +1655,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        bgx_init_hw(bgx);
 
+       bgx_register_intr(pdev);
+
        /* Enable all LMACs */
        for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
                err = bgx_lmac_enable(bgx, lmac);
@@ -1620,6 +1673,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 err_enable:
        bgx_vnic[bgx->bgx_id] = NULL;
+       pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
 err_release_regions:
        pci_release_regions(pdev);
 err_disable_device:
@@ -1637,6 +1691,8 @@ static void bgx_remove(struct pci_dev *pdev)
        for (lmac = 0; lmac < bgx->lmac_count; lmac++)
                bgx_lmac_disable(bgx, lmac);
 
+       pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+
        bgx_vnic[bgx->bgx_id] = NULL;
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index 25888706bdcd1115e2824c88df23aff273b62171..cdea4939218578cd8424ad632702ce4e00104130 100644 (file)
 #define BGX_GMP_GMI_TXX_BURST          0x38228
 #define BGX_GMP_GMI_TXX_MIN_PKT                0x38240
 #define BGX_GMP_GMI_TXX_SGMII_CTL      0x38300
+#define BGX_GMP_GMI_TXX_INT            0x38500
+#define BGX_GMP_GMI_TXX_INT_W1S                0x38508
+#define BGX_GMP_GMI_TXX_INT_ENA_W1C    0x38510
+#define BGX_GMP_GMI_TXX_INT_ENA_W1S    0x38518
+#define  GMI_TXX_INT_PTP_LOST                  BIT_ULL(4)
+#define  GMI_TXX_INT_LATE_COL                  BIT_ULL(3)
+#define  GMI_TXX_INT_XSDEF                     BIT_ULL(2)
+#define  GMI_TXX_INT_XSCOL                     BIT_ULL(1)
+#define  GMI_TXX_INT_UNDFLW                    BIT_ULL(0)
 
 #define BGX_MSIX_VEC_0_29_ADDR         0x400000 /* +(0..29) << 4 */
 #define BGX_MSIX_VEC_0_29_CTL          0x400008
index 1ea3372775e6daa39c300e2624f921742cb5f29e..e94ae9b94dbfceea2c44065ad58d624676b5dd8f 100644 (file)
@@ -1405,6 +1405,8 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
                ether_addr_copy(pdata->dev_addr, mac_addr);
+       else if (PTR_ERR(mac_addr) == -EPROBE_DEFER)
+               return ERR_CAST(mac_addr);
 
        return pdata;
 }
index 6f2cf569a283cb8f53ce653d7ab2c72fb2ca0799..79b3d53f2fbfa73d89ecd1f5490072da9503c0e9 100644 (file)
@@ -297,6 +297,7 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
        }
 
        hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
+       hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
 
        hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
        hw_ioctxt.cmdq_depth = 0;
index b069045de416c582660e06b5f98db3869e09478b..66fd2340d44795bc3bc56071f801e50c26d7e1ea 100644 (file)
@@ -151,8 +151,8 @@ struct hinic_cmd_hw_ioctxt {
 
        u8      lro_en;
        u8      rsvd3;
+       u8      ppf_idx;
        u8      rsvd4;
-       u8      rsvd5;
 
        u16     rq_depth;
        u16     rx_buf_sz_idx;
index 517794509eb295cb0217e2df4ba43c1767ccaa9a..c7bb9ceca72cac90d85a6a11966c5771e7eee486 100644 (file)
 #define HINIC_HWIF_FUNC_IDX(hwif)       ((hwif)->attr.func_idx)
 #define HINIC_HWIF_PCI_INTF(hwif)       ((hwif)->attr.pci_intf_idx)
 #define HINIC_HWIF_PF_IDX(hwif)         ((hwif)->attr.pf_idx)
+#define HINIC_HWIF_PPF_IDX(hwif)        ((hwif)->attr.ppf_idx)
 
 #define HINIC_FUNC_TYPE(hwif)           ((hwif)->attr.func_type)
 #define HINIC_IS_PF(hwif)               (HINIC_FUNC_TYPE(hwif) == HINIC_PF)
index f4a339b10b10b55c86da6080adf12b3248b58534..79091e1314181e3493c9e54760ca4671936337e1 100644 (file)
@@ -94,6 +94,7 @@ struct hinic_rq {
 
        struct hinic_wq         *wq;
 
+       struct cpumask          affinity_mask;
        u32                     irq;
        u16                     msix_entry;
 
index 02a14f5e7fe31ddc28fe5a3720e081d5346db653..13560975c103a29438b4e00542561a4b796abb1f 100644 (file)
@@ -356,7 +356,8 @@ static void hinic_enable_rss(struct hinic_dev *nic_dev)
        if (!num_cpus)
                num_cpus = num_online_cpus();
 
-       nic_dev->num_qps = min_t(u16, nic_dev->max_qps, num_cpus);
+       nic_dev->num_qps = hinic_hwdev_num_qps(hwdev);
+       nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus);
 
        nic_dev->rss_limit = nic_dev->num_qps;
        nic_dev->num_rss = nic_dev->num_qps;
index 56ea6d692f1c3dda7fd329c555d1a70696c0dd1a..2695ad69fca600c469762643ebd804f6bdfade1d 100644 (file)
@@ -475,7 +475,6 @@ static int rx_request_irq(struct hinic_rxq *rxq)
        struct hinic_hwdev *hwdev = nic_dev->hwdev;
        struct hinic_rq *rq = rxq->rq;
        struct hinic_qp *qp;
-       struct cpumask mask;
        int err;
 
        rx_add_napi(rxq);
@@ -492,8 +491,8 @@ static int rx_request_irq(struct hinic_rxq *rxq)
        }
 
        qp = container_of(rq, struct hinic_qp, rq);
-       cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask);
-       return irq_set_affinity_hint(rq->irq, &mask);
+       cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask);
+       return irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
 }
 
 static void rx_free_irq(struct hinic_rxq *rxq)
index b002ab4e5838cebafcc9433881d98cda0817afcf..77c412a7e7a47f4842dfd3c0ec96c3415aa39178 100644 (file)
@@ -2936,13 +2936,6 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
        else
                return -EINVAL;
 
-       /* Tell the OS link is going down, the link will go back up when fw
-        * says it is ready asynchronously
-        */
-       ice_print_link_msg(vsi, false);
-       netif_carrier_off(netdev);
-       netif_tx_stop_all_queues(netdev);
-
        /* Set the FC mode and only restart AN if link is up */
        status = ice_set_fc(pi, &aq_failures, link_up);
 
@@ -3489,21 +3482,13 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
                return -EINVAL;
        }
 
-       /* hardware only supports an ITR granularity of 2us */
-       if (coalesce_usecs % 2 != 0) {
-               netdev_info(vsi->netdev, "Invalid value, %s-usecs must be even\n",
-                           c_type_str);
-               return -EINVAL;
-       }
-
        if (use_adaptive_coalesce) {
                rc->itr_setting |= ICE_ITR_DYNAMIC;
        } else {
-               /* store user facing value how it was set */
+               /* save the user set usecs */
                rc->itr_setting = coalesce_usecs;
-               /* set to static and convert to value HW understands */
-               rc->target_itr =
-                       ITR_TO_REG(ITR_REG_ALIGN(rc->itr_setting));
+               /* device ITR granularity is in 2 usec increments */
+               rc->target_itr = ITR_REG_ALIGN(rc->itr_setting);
        }
 
        return 0;
@@ -3596,6 +3581,30 @@ ice_is_coalesce_param_invalid(struct net_device *netdev,
        return 0;
 }
 
+/**
+ * ice_print_if_odd_usecs - print message if user tries to set odd [tx|rx]-usecs
+ * @netdev: netdev used for print
+ * @itr_setting: previous user setting
+ * @use_adaptive_coalesce: if adaptive coalesce is enabled or being enabled
+ * @coalesce_usecs: requested value of [tx|rx]-usecs
+ * @c_type_str: either "rx" or "tx" to match user set field of [tx|rx]-usecs
+ */
+static void
+ice_print_if_odd_usecs(struct net_device *netdev, u16 itr_setting,
+                      u32 use_adaptive_coalesce, u32 coalesce_usecs,
+                      const char *c_type_str)
+{
+       if (use_adaptive_coalesce)
+               return;
+
+       itr_setting = ITR_TO_REG(itr_setting);
+
+       if (itr_setting != coalesce_usecs && (coalesce_usecs % 2))
+               netdev_info(netdev, "User set %s-usecs to %d, device only supports even values. Rounding down and attempting to set %s-usecs to %d\n",
+                           c_type_str, coalesce_usecs, c_type_str,
+                           ITR_REG_ALIGN(coalesce_usecs));
+}
+
 /**
  * __ice_set_coalesce - set ITR/INTRL values for the device
  * @netdev: pointer to the netdev associated with this query
@@ -3616,8 +3625,19 @@ __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec,
                return -EINVAL;
 
        if (q_num < 0) {
+               struct ice_q_vector *q_vector = vsi->q_vectors[0];
                int v_idx;
 
+               if (q_vector) {
+                       ice_print_if_odd_usecs(netdev, q_vector->rx.itr_setting,
+                                              ec->use_adaptive_rx_coalesce,
+                                              ec->rx_coalesce_usecs, "rx");
+
+                       ice_print_if_odd_usecs(netdev, q_vector->tx.itr_setting,
+                                              ec->use_adaptive_tx_coalesce,
+                                              ec->tx_coalesce_usecs, "tx");
+               }
+
                ice_for_each_q_vector(vsi, v_idx) {
                        /* In some cases if DCB is configured the num_[rx|tx]q
                         * can be less than vsi->num_q_vectors. This check
index 14a1bf445889fc4f4f282449bb50938db253cb71..7ee00a1286634a5eed591f5d22c5a29ebbc79cf3 100644 (file)
@@ -222,7 +222,7 @@ enum ice_rx_dtype {
 #define ICE_ITR_GRAN_S         1       /* ITR granularity is always 2us */
 #define ICE_ITR_GRAN_US                BIT(ICE_ITR_GRAN_S)
 #define ICE_ITR_MASK           0x1FFE  /* ITR register value alignment mask */
-#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK)
+#define ITR_REG_ALIGN(setting) ((setting) & ICE_ITR_MASK)
 
 #define ICE_ITR_ADAPTIVE_MIN_INC       0x0002
 #define ICE_ITR_ADAPTIVE_MIN_USECS     0x0002
index 262714d5f54a7e72d7660cad3e6f6f70ab0984f1..75c70d432c7245e1c76f1b0a39cdfa4be5d62dc9 100644 (file)
@@ -1873,6 +1873,48 @@ error_param:
                                     NULL, 0);
 }
 
+/**
+ * ice_wait_on_vf_reset - poll to make sure a given VF is ready after reset
+ * @vf: The VF being resseting
+ *
+ * The max poll time is about ~800ms, which is about the maximum time it takes
+ * for a VF to be reset and/or a VF driver to be removed.
+ */
+static void ice_wait_on_vf_reset(struct ice_vf *vf)
+{
+       int i;
+
+       for (i = 0; i < ICE_MAX_VF_RESET_TRIES; i++) {
+               if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
+                       break;
+               msleep(ICE_MAX_VF_RESET_SLEEP_MS);
+       }
+}
+
+/**
+ * ice_check_vf_ready_for_cfg - check if VF is ready to be configured/queried
+ * @vf: VF to check if it's ready to be configured/queried
+ *
+ * The purpose of this function is to make sure the VF is not in reset, not
+ * disabled, and initialized so it can be configured and/or queried by a host
+ * administrator.
+ */
+static int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
+{
+       struct ice_pf *pf;
+
+       ice_wait_on_vf_reset(vf);
+
+       if (ice_is_vf_disabled(vf))
+               return -EINVAL;
+
+       pf = vf->pf;
+       if (ice_check_vf_init(pf, vf))
+               return -EBUSY;
+
+       return 0;
+}
+
 /**
  * ice_set_vf_spoofchk
  * @netdev: network interface device structure
@@ -1890,16 +1932,16 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
        enum ice_status status;
        struct device *dev;
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        vf_vsi = pf->vsi[vf->lan_vsi_idx];
        if (!vf_vsi) {
@@ -2696,7 +2738,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
        struct ice_vsi *vsi;
        struct device *dev;
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id))
@@ -2714,13 +2756,15 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
 
        vf = &pf->vf[vf_id];
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        if (le16_to_cpu(vsi->info.pvid) == vlanprio) {
                /* duplicate request, so just return success */
                dev_dbg(dev, "Duplicate pvid %d request\n", vlanprio);
-               return ret;
+               return 0;
        }
 
        /* If PVID, then remove all filters on the old VLAN */
@@ -2731,7 +2775,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
        if (vlan_id || qos) {
                ret = ice_vsi_manage_pvid(vsi, vlanprio, true);
                if (ret)
-                       goto error_set_pvid;
+                       return ret;
        } else {
                ice_vsi_manage_pvid(vsi, 0, false);
                vsi->info.pvid = 0;
@@ -2744,7 +2788,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
                /* add new VLAN filter for each MAC */
                ret = ice_vsi_add_vlan(vsi, vlan_id);
                if (ret)
-                       goto error_set_pvid;
+                       return ret;
        }
 
        /* The Port VLAN needs to be saved across resets the same as the
@@ -2752,8 +2796,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
         */
        vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
 
-error_set_pvid:
-       return ret;
+       return 0;
 }
 
 /**
@@ -3236,23 +3279,6 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
        return 0;
 }
 
-/**
- * ice_wait_on_vf_reset
- * @vf: The VF being resseting
- *
- * Poll to make sure a given VF is ready after reset
- */
-static void ice_wait_on_vf_reset(struct ice_vf *vf)
-{
-       int i;
-
-       for (i = 0; i < ICE_MAX_VF_RESET_WAIT; i++) {
-               if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
-                       break;
-               msleep(20);
-       }
-}
-
 /**
  * ice_set_vf_mac
  * @netdev: network interface device structure
@@ -3265,29 +3291,21 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
-       vf = &pf->vf[vf_id];
-       /* Don't set MAC on disabled VF */
-       if (ice_is_vf_disabled(vf))
-               return -EINVAL;
-
-       /* In case VF is in reset mode, wait until it is completed. Depending
-        * on factors like queue disabling routine, this could take ~250ms
-        */
-       ice_wait_on_vf_reset(vf);
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
-
        if (is_zero_ether_addr(mac) || is_multicast_ether_addr(mac)) {
                netdev_err(netdev, "%pM not a valid unicast address\n", mac);
                return -EINVAL;
        }
 
+       vf = &pf->vf[vf_id];
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
+
        /* copy MAC into dflt_lan_addr and trigger a VF reset. The reset
         * flow will use the updated dflt_lan_addr and add a MAC filter
         * using ice_add_mac. Also set pf_set_mac to indicate that the PF has
@@ -3299,7 +3317,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
                    vf_id, mac);
 
        ice_vc_reset_vf(vf);
-       return ret;
+       return 0;
 }
 
 /**
@@ -3314,22 +3332,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-       /* Don't set Trusted Mode on disabled VF */
-       if (ice_is_vf_disabled(vf))
-               return -EINVAL;
-
-       /* In case VF is in reset mode, wait until it is completed. Depending
-        * on factors like queue disabling routine, this could take ~250ms
-        */
-       ice_wait_on_vf_reset(vf);
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        /* Check if already trusted */
        if (trusted == vf->trusted)
@@ -3355,13 +3366,15 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        switch (link_state) {
        case IFLA_VF_LINK_STATE_AUTO:
@@ -3397,14 +3410,15 @@ int ice_get_vf_stats(struct net_device *netdev, int vf_id,
        struct ice_eth_stats *stats;
        struct ice_vsi *vsi;
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        vsi = pf->vsi[vf->lan_vsi_idx];
        if (!vsi)
index 4647d636ed36e07c921f5e4c903f43effde7bc93..ac67982751dfb517dc050331b44a4c580de96de2 100644 (file)
@@ -38,7 +38,8 @@
 #define ICE_MAX_POLICY_INTR_PER_VF     33
 #define ICE_MIN_INTR_PER_VF            (ICE_MIN_QS_PER_VF + 1)
 #define ICE_DFLT_INTR_PER_VF           (ICE_DFLT_QS_PER_VF + 1)
-#define ICE_MAX_VF_RESET_WAIT          15
+#define ICE_MAX_VF_RESET_TRIES         40
+#define ICE_MAX_VF_RESET_SLEEP_MS      20
 
 #define ice_for_each_vf(pf, i) \
        for ((i) = 0; (i) < (pf)->num_alloc_vfs; (i)++)
index 3a975641f902adbb5da9286e39dbe3bb84c71b61..20b907dc1e297ff697cae883f5c8e6978b1e576c 100644 (file)
@@ -200,7 +200,7 @@ int mlx5e_health_report(struct mlx5e_priv *priv,
        netdev_err(priv->netdev, err_str);
 
        if (!reporter)
-               return err_ctx->recover(&err_ctx->ctx);
+               return err_ctx->recover(err_ctx->ctx);
 
        return devlink_health_report(reporter, err_str, err_ctx);
 }
index 7c8796d9743fa5a6c66f4aa3e0017b800a121a9b..a226277b09805a75a107e069db46801ffa1c454c 100644 (file)
@@ -179,6 +179,14 @@ mlx5e_tx_dma_unmap(struct device *pdev, struct mlx5e_sq_dma *dma)
        }
 }
 
+static inline void mlx5e_rqwq_reset(struct mlx5e_rq *rq)
+{
+       if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
+               mlx5_wq_ll_reset(&rq->mpwqe.wq);
+       else
+               mlx5_wq_cyc_reset(&rq->wqe.wq);
+}
+
 /* SW parser related functions */
 
 struct mlx5e_swp_spec {
index 454d3459bd8b9639f2207dd2b5b0aef08e296aa5..21de4764d4c09b933a39b476b2509c5e3896204b 100644 (file)
@@ -712,6 +712,9 @@ int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_state)
        if (!in)
                return -ENOMEM;
 
+       if (curr_state == MLX5_RQC_STATE_RST && next_state == MLX5_RQC_STATE_RDY)
+               mlx5e_rqwq_reset(rq);
+
        rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
 
        MLX5_SET(modify_rq_in, in, rq_state, curr_state);
@@ -5144,7 +5147,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
-       struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
 
 #ifdef CONFIG_MLX5_CORE_EN_DCB
@@ -5165,7 +5167,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
                mlx5e_monitor_counter_cleanup(priv);
 
        mlx5e_disable_async_events(priv);
-       mlx5_lag_remove(mdev, netdev);
+       mlx5_lag_remove(mdev);
 }
 
 int mlx5e_update_nic_rx(struct mlx5e_priv *priv)
index 7b48ccacebe29bdaf7a46f610869bec31e469b34..6ed307d7f191499af3f80d2f4a5a0cdb48878eb6 100644 (file)
@@ -1861,7 +1861,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 {
-       struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
 
@@ -1870,7 +1869,7 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 #endif
        mlx5_notifier_unregister(mdev, &priv->events_nb);
        cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
-       mlx5_lag_remove(mdev, netdev);
+       mlx5_lag_remove(mdev);
 }
 
 static MLX5E_DEFINE_STATS_GRP(sw_rep, 0);
index 5acf60b1bbfed5ba230fb57ec28c418f16ccab44..e49acd0c5da5cf27ffe78b386da4535f4a36091a 100644 (file)
@@ -459,12 +459,16 @@ static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
 
 static int esw_legacy_enable(struct mlx5_eswitch *esw)
 {
-       int ret;
+       struct mlx5_vport *vport;
+       int ret, i;
 
        ret = esw_create_legacy_table(esw);
        if (ret)
                return ret;
 
+       mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
+               vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+
        ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
        if (ret)
                esw_destroy_legacy_table(esw);
@@ -2452,25 +2456,17 @@ out:
 
 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
 {
-       int err = 0;
-
        if (!esw)
                return -EOPNOTSUPP;
 
        if (!ESW_ALLOWED(esw))
                return -EPERM;
 
-       mutex_lock(&esw->state_lock);
-       if (esw->mode != MLX5_ESWITCH_LEGACY) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
+       if (esw->mode != MLX5_ESWITCH_LEGACY)
+               return -EOPNOTSUPP;
 
        *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
-
-out:
-       mutex_unlock(&esw->state_lock);
-       return err;
+       return 0;
 }
 
 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
index 979f13bdc203a48c2b7c53a454d9e41f1389a790..1a57b2bd74b8650c070f1c0ad80b4c7069ad502b 100644 (file)
@@ -1172,7 +1172,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
                return -EINVAL;
        }
 
-       mlx5_eswitch_disable(esw, true);
+       mlx5_eswitch_disable(esw, false);
        mlx5_eswitch_update_num_of_vfs(esw, esw->dev->priv.sriov.num_vfs);
        err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_OFFLOADS);
        if (err) {
@@ -2065,7 +2065,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
 {
        int err, err1;
 
-       mlx5_eswitch_disable(esw, true);
+       mlx5_eswitch_disable(esw, false);
        err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_LEGACY);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy");
index c5a446e295aa7d9b522cb0a145edd199bd120c2e..4276194b633fd1ef25a00982c9bb5f2ea51b18a5 100644 (file)
@@ -35,7 +35,7 @@
 static const unsigned int ESW_POOLS[] = { 4 * 1024 * 1024,
                                          1 * 1024 * 1024,
                                          64 * 1024,
-                                         4 * 1024, };
+                                         128 };
 
 struct mlx5_esw_chains_priv {
        struct rhashtable chains_ht;
index b91eabc09fbc187460750f6bc10465ae1b3be944..8e19f6ab8393202c6c15791d9daa220c8536b512 100644 (file)
@@ -464,9 +464,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
        struct mlx5_lag *ldev;
        int changed = 0;
 
-       if (!net_eq(dev_net(ndev), &init_net))
-               return NOTIFY_DONE;
-
        if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE))
                return NOTIFY_DONE;
 
@@ -586,8 +583,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
 
        if (!ldev->nb.notifier_call) {
                ldev->nb.notifier_call = mlx5_lag_netdev_event;
-               if (register_netdevice_notifier_dev_net(netdev, &ldev->nb,
-                                                       &ldev->nn)) {
+               if (register_netdevice_notifier_net(&init_net, &ldev->nb)) {
                        ldev->nb.notifier_call = NULL;
                        mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
                }
@@ -600,7 +596,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
 }
 
 /* Must be called with intf_mutex held */
-void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev)
+void mlx5_lag_remove(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
        int i;
@@ -620,8 +616,7 @@ void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev)
 
        if (i == MLX5_MAX_PORTS) {
                if (ldev->nb.notifier_call)
-                       unregister_netdevice_notifier_dev_net(netdev, &ldev->nb,
-                                                             &ldev->nn);
+                       unregister_netdevice_notifier_net(&init_net, &ldev->nb);
                mlx5_lag_mp_cleanup(ldev);
                cancel_delayed_work_sync(&ldev->bond_work);
                mlx5_lag_dev_free(ldev);
index 316ab09e26645a59b34a60e61a33db3185d3c2fb..f1068aac64067080234ddb89fdaf68631698f7fa 100644 (file)
@@ -44,7 +44,6 @@ struct mlx5_lag {
        struct workqueue_struct   *wq;
        struct delayed_work       bond_work;
        struct notifier_block     nb;
-       struct netdev_net_notifier      nn;
        struct lag_mp             lag_mp;
 };
 
index fcce9e0fc82c8e3f2d240cfbaa1cfdd6f0a51f3f..da67b28d6e23e621bac2c014b26cf811274ed10f 100644 (file)
@@ -157,7 +157,7 @@ int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
                        u8 feature_group, u8 access_reg_group);
 
 void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev);
-void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev);
+void mlx5_lag_remove(struct mlx5_core_dev *dev);
 
 int mlx5_irq_table_init(struct mlx5_core_dev *dev);
 void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
index c6c7d1defbd788ee657f45c8e3914c6e8393243e..aade62a9ee5ce93e59c9ffb139665d9eaf277b5b 100644 (file)
@@ -2307,7 +2307,9 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_cmd_vport_cap *vport_cap;
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_cmd_caps *caps;
+       u8 *bit_mask = sb->bit_mask;
        u8 *tag = hw_ste->tag;
+       bool source_gvmi_set;
 
        DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
 
@@ -2328,7 +2330,8 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        if (!vport_cap)
                return -EINVAL;
 
-       if (vport_cap->vport_gvmi)
+       source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi);
+       if (vport_cap->vport_gvmi && source_gvmi_set)
                MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
 
        misc->source_eswitch_owner_vhca_id = 0;
index 3abfc81259262d94a327b24b34d00b89d5409288..c2027192e21e8c8a298e915e161ea592d17b83f6 100644 (file)
@@ -66,15 +66,20 @@ static int mlx5_cmd_dr_create_flow_table(struct mlx5_flow_root_namespace *ns,
                                         struct mlx5_flow_table *next_ft)
 {
        struct mlx5dr_table *tbl;
+       u32 flags;
        int err;
 
        if (mlx5_dr_is_fw_table(ft->flags))
                return mlx5_fs_cmd_get_fw_cmds()->create_flow_table(ns, ft,
                                                                    log_size,
                                                                    next_ft);
+       flags = ft->flags;
+       /* turn off encap/decap if not supported for sw-str by fw */
+       if (!MLX5_CAP_FLOWTABLE(ns->dev, sw_owner_reformat_supported))
+               flags = ft->flags & ~(MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
+                                     MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 
-       tbl = mlx5dr_table_create(ns->fs_dr_domain.dr_domain,
-                                 ft->level, ft->flags);
+       tbl = mlx5dr_table_create(ns->fs_dr_domain.dr_domain, ft->level, flags);
        if (!tbl) {
                mlx5_core_err(ns->dev, "Failed creating dr flow_table\n");
                return -EINVAL;
index 02f7e4a39578a33f04e030c32e1da47a322d09aa..01f075fac2765d2ad85651fbca2bf59195dcbfe1 100644 (file)
@@ -94,6 +94,13 @@ void mlx5_wq_cyc_wqe_dump(struct mlx5_wq_cyc *wq, u16 ix, u8 nstrides)
        print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, wqe, len, false);
 }
 
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq)
+{
+       wq->wqe_ctr = 0;
+       wq->cur_sz = 0;
+       mlx5_wq_cyc_update_db_record(wq);
+}
+
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *qpc, struct mlx5_wq_qp *wq,
                      struct mlx5_wq_ctrl *wq_ctrl)
@@ -192,6 +199,19 @@ err_db_free:
        return err;
 }
 
+static void mlx5_wq_ll_init_list(struct mlx5_wq_ll *wq)
+{
+       struct mlx5_wqe_srq_next_seg *next_seg;
+       int i;
+
+       for (i = 0; i < wq->fbc.sz_m1; i++) {
+               next_seg = mlx5_wq_ll_get_wqe(wq, i);
+               next_seg->next_wqe_index = cpu_to_be16(i + 1);
+       }
+       next_seg = mlx5_wq_ll_get_wqe(wq, i);
+       wq->tail_next = &next_seg->next_wqe_index;
+}
+
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *wqc, struct mlx5_wq_ll *wq,
                      struct mlx5_wq_ctrl *wq_ctrl)
@@ -199,9 +219,7 @@ int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
        u8 log_wq_stride = MLX5_GET(wq, wqc, log_wq_stride);
        u8 log_wq_sz     = MLX5_GET(wq, wqc, log_wq_sz);
        struct mlx5_frag_buf_ctrl *fbc = &wq->fbc;
-       struct mlx5_wqe_srq_next_seg *next_seg;
        int err;
-       int i;
 
        err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
        if (err) {
@@ -220,13 +238,7 @@ int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 
        mlx5_init_fbc(wq_ctrl->buf.frags, log_wq_stride, log_wq_sz, fbc);
 
-       for (i = 0; i < fbc->sz_m1; i++) {
-               next_seg = mlx5_wq_ll_get_wqe(wq, i);
-               next_seg->next_wqe_index = cpu_to_be16(i + 1);
-       }
-       next_seg = mlx5_wq_ll_get_wqe(wq, i);
-       wq->tail_next = &next_seg->next_wqe_index;
-
+       mlx5_wq_ll_init_list(wq);
        wq_ctrl->mdev = mdev;
 
        return 0;
@@ -237,6 +249,15 @@ err_db_free:
        return err;
 }
 
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq)
+{
+       wq->head = 0;
+       wq->wqe_ctr = 0;
+       wq->cur_sz = 0;
+       mlx5_wq_ll_init_list(wq);
+       mlx5_wq_ll_update_db_record(wq);
+}
+
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl)
 {
        mlx5_frag_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
index d9a94bc223c05d470ba1cc58a1bf2a04086e1e27..4cadc336593f1cf76321ff6f85e940ea35297a10 100644 (file)
@@ -80,6 +80,7 @@ int mlx5_wq_cyc_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                       void *wqc, struct mlx5_wq_cyc *wq,
                       struct mlx5_wq_ctrl *wq_ctrl);
 void mlx5_wq_cyc_wqe_dump(struct mlx5_wq_cyc *wq, u16 ix, u8 nstrides);
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq);
 
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *qpc, struct mlx5_wq_qp *wq,
@@ -92,6 +93,7 @@ int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *wqc, struct mlx5_wq_ll *wq,
                      struct mlx5_wq_ctrl *wq_ctrl);
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq);
 
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl);
 
index e0d7d2d9a0c81c8df137a6b01ea17c0f9066e169..43fa8c85b5d9f85d0892adbfdf28d482bb4c7e39 100644 (file)
@@ -28,7 +28,7 @@
 #define MLXSW_PCI_SW_RESET                     0xF0010
 #define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
 #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       900000
-#define MLXSW_PCI_SW_RESET_WAIT_MSECS          100
+#define MLXSW_PCI_SW_RESET_WAIT_MSECS          200
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
 #define MLXSW_PCI_FW_READY_MAGIC               0x5E
index a41a90c589db2d2e85863e6da3850307d5e2a488..58579baf3f7a007f65910938b7e3a7f3ddaed718 100644 (file)
@@ -156,24 +156,6 @@ static int msg_enable;
  * chip is busy transferring packet data (RX/TX FIFO accesses).
  */
 
-/**
- * ks_rdreg8 - read 8 bit register from device
- * @ks   : The chip information
- * @offset: The register address
- *
- * Read a 8bit register from the chip, returning the result
- */
-static u8 ks_rdreg8(struct ks_net *ks, int offset)
-{
-       u16 data;
-       u8 shift_bit = offset & 0x03;
-       u8 shift_data = (offset & 1) << 3;
-       ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit);
-       iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-       data  = ioread16(ks->hw_addr);
-       return (u8)(data >> shift_data);
-}
-
 /**
  * ks_rdreg16 - read 16 bit register from device
  * @ks   : The chip information
@@ -184,27 +166,11 @@ static u8 ks_rdreg8(struct ks_net *ks, int offset)
 
 static u16 ks_rdreg16(struct ks_net *ks, int offset)
 {
-       ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+       ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02));
        iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
        return ioread16(ks->hw_addr);
 }
 
-/**
- * ks_wrreg8 - write 8bit register value to chip
- * @ks: The chip information
- * @offset: The register address
- * @value: The value to write
- *
- */
-static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
-{
-       u8  shift_bit = (offset & 0x03);
-       u16 value_write = (u16)(value << ((offset & 1) << 3));
-       ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit);
-       iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-       iowrite16(value_write, ks->hw_addr);
-}
-
 /**
  * ks_wrreg16 - write 16bit register value to chip
  * @ks: The chip information
@@ -215,7 +181,7 @@ static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
 
 static void ks_wrreg16(struct ks_net *ks, int offset, u16 value)
 {
-       ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+       ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02));
        iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
        iowrite16(value, ks->hw_addr);
 }
@@ -231,7 +197,7 @@ static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len)
 {
        len >>= 1;
        while (len--)
-               *wptr++ = (u16)ioread16(ks->hw_addr);
+               *wptr++ = be16_to_cpu(ioread16(ks->hw_addr));
 }
 
 /**
@@ -245,7 +211,7 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len)
 {
        len >>= 1;
        while (len--)
-               iowrite16(*wptr++, ks->hw_addr);
+               iowrite16(cpu_to_be16(*wptr++), ks->hw_addr);
 }
 
 static void ks_disable_int(struct ks_net *ks)
@@ -324,8 +290,7 @@ static void ks_read_config(struct ks_net *ks)
        u16 reg_data = 0;
 
        /* Regardless of bus width, 8 bit read should always work.*/
-       reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF;
-       reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8;
+       reg_data = ks_rdreg16(ks, KS_CCR);
 
        /* addr/data bus are multiplexed */
        ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
@@ -429,7 +394,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len)
 
        /* 1. set sudo DMA mode */
        ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI);
-       ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
 
        /* 2. read prepend data */
        /**
@@ -446,7 +411,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len)
        ks_inblk(ks, buf, ALIGN(len, 4));
 
        /* 4. reset sudo DMA Mode */
-       ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
 }
 
 /**
@@ -548,14 +513,17 @@ static irqreturn_t ks_irq(int irq, void *pw)
 {
        struct net_device *netdev = pw;
        struct ks_net *ks = netdev_priv(netdev);
+       unsigned long flags;
        u16 status;
 
+       spin_lock_irqsave(&ks->statelock, flags);
        /*this should be the first in IRQ handler */
        ks_save_cmd_reg(ks);
 
        status = ks_rdreg16(ks, KS_ISR);
        if (unlikely(!status)) {
                ks_restore_cmd_reg(ks);
+               spin_unlock_irqrestore(&ks->statelock, flags);
                return IRQ_NONE;
        }
 
@@ -581,6 +549,7 @@ static irqreturn_t ks_irq(int irq, void *pw)
                ks->netdev->stats.rx_over_errors++;
        /* this should be the last in IRQ handler*/
        ks_restore_cmd_reg(ks);
+       spin_unlock_irqrestore(&ks->statelock, flags);
        return IRQ_HANDLED;
 }
 
@@ -650,6 +619,7 @@ static int ks_net_stop(struct net_device *netdev)
 
        /* shutdown RX/TX QMU */
        ks_disable_qmu(ks);
+       ks_disable_int(ks);
 
        /* set powermode to soft power down to save power */
        ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
@@ -679,13 +649,13 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len)
        ks->txh.txw[1] = cpu_to_le16(len);
 
        /* 1. set sudo-DMA mode */
-       ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
        /* 2. write status/lenth info */
        ks_outblk(ks, ks->txh.txw, 4);
        /* 3. write pkt data */
        ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4));
        /* 4. reset sudo-DMA mode */
-       ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
        /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
        ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
        /* 6. wait until TXQCR_METFE is auto-cleared */
@@ -706,10 +676,9 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        netdev_tx_t retv = NETDEV_TX_OK;
        struct ks_net *ks = netdev_priv(netdev);
+       unsigned long flags;
 
-       disable_irq(netdev->irq);
-       ks_disable_int(ks);
-       spin_lock(&ks->statelock);
+       spin_lock_irqsave(&ks->statelock, flags);
 
        /* Extra space are required:
        *  4 byte for alignment, 4 for status/length, 4 for CRC
@@ -723,9 +692,7 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                dev_kfree_skb(skb);
        } else
                retv = NETDEV_TX_BUSY;
-       spin_unlock(&ks->statelock);
-       ks_enable_int(ks);
-       enable_irq(netdev->irq);
+       spin_unlock_irqrestore(&ks->statelock, flags);
        return retv;
 }
 
index b38820849faab9d23bcd7f06e2a0637819c96647..1135a18019c77faf4ff7c42a90de630644d8364a 100644 (file)
@@ -114,6 +114,14 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                if (err != 4)
                        break;
 
+               /* At this point the IFH was read correctly, so it is safe to
+                * presume that there is no error. The err needs to be reset
+                * otherwise a frame could come in CPU queue between the while
+                * condition and the check for error later on. And in that case
+                * the new frame is just removed and not processed.
+                */
+               err = 0;
+
                ocelot_parse_ifh(ifh, &info);
 
                ocelot_port = ocelot->ports[info.port];
index 87f82f36812ffaa52d5dae0d191581b61c4fda15..46107de5e6c3bfb0fcc526ef46f642595c0b7304 100644 (file)
@@ -103,7 +103,7 @@ int ionic_heartbeat_check(struct ionic *ionic)
 {
        struct ionic_dev *idev = &ionic->idev;
        unsigned long hb_time;
-       u32 fw_status;
+       u8 fw_status;
        u32 hb;
 
        /* wait a little more than one second before testing again */
@@ -111,9 +111,12 @@ int ionic_heartbeat_check(struct ionic *ionic)
        if (time_before(hb_time, (idev->last_hb_time + ionic->watchdog_period)))
                return 0;
 
-       /* firmware is useful only if fw_status is non-zero */
-       fw_status = ioread32(&idev->dev_info_regs->fw_status);
-       if (!fw_status)
+       /* firmware is useful only if the running bit is set and
+        * fw_status != 0xff (bad PCI read)
+        */
+       fw_status = ioread8(&idev->dev_info_regs->fw_status);
+       if (fw_status == 0xff ||
+           !(fw_status & IONIC_FW_STS_F_RUNNING))
                return -ENXIO;
 
        /* early FW has no heartbeat, else FW will return non-zero */
index ce07c2931a727a4e2571803f9d986dafe6c2e0b2..54547d53b0f22c62feda507af8a0fb1a14664f85 100644 (file)
@@ -2445,6 +2445,7 @@ union ionic_dev_info_regs {
                u8     version;
                u8     asic_type;
                u8     asic_rev;
+#define IONIC_FW_STS_F_RUNNING 0x1
                u8     fw_status;
                u32    fw_heartbeat;
                char   fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];
index e8a1b27db84debab0aad020a869660bc310b2b80..234c6f30effb7ff12ab6d0ea2cbd3e08b4610dec 100644 (file)
@@ -163,6 +163,8 @@ struct qede_rdma_dev {
        struct list_head entry;
        struct list_head rdma_event_list;
        struct workqueue_struct *rdma_wq;
+       struct kref refcnt;
+       struct completion event_comp;
        bool exp_recovery;
 };
 
index ffabc2d2f082444e85a546db4a5b10a460a59c16..2d873ae8a234d2520a79febe99d740e3e4b95913 100644 (file)
@@ -59,6 +59,9 @@ static void _qede_rdma_dev_add(struct qede_dev *edev)
 static int qede_rdma_create_wq(struct qede_dev *edev)
 {
        INIT_LIST_HEAD(&edev->rdma_info.rdma_event_list);
+       kref_init(&edev->rdma_info.refcnt);
+       init_completion(&edev->rdma_info.event_comp);
+
        edev->rdma_info.rdma_wq = create_singlethread_workqueue("rdma_wq");
        if (!edev->rdma_info.rdma_wq) {
                DP_NOTICE(edev, "qedr: Could not create workqueue\n");
@@ -83,8 +86,23 @@ static void qede_rdma_cleanup_event(struct qede_dev *edev)
        }
 }
 
+static void qede_rdma_complete_event(struct kref *ref)
+{
+       struct qede_rdma_dev *rdma_dev =
+               container_of(ref, struct qede_rdma_dev, refcnt);
+
+       /* no more events will be added after this */
+       complete(&rdma_dev->event_comp);
+}
+
 static void qede_rdma_destroy_wq(struct qede_dev *edev)
 {
+       /* Avoid race with add_event flow, make sure it finishes before
+        * we start accessing the list and cleaning up the work
+        */
+       kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
+       wait_for_completion(&edev->rdma_info.event_comp);
+
        qede_rdma_cleanup_event(edev);
        destroy_workqueue(edev->rdma_info.rdma_wq);
 }
@@ -310,15 +328,24 @@ static void qede_rdma_add_event(struct qede_dev *edev,
        if (!edev->rdma_info.qedr_dev)
                return;
 
+       /* We don't want the cleanup flow to start while we're allocating and
+        * scheduling the work
+        */
+       if (!kref_get_unless_zero(&edev->rdma_info.refcnt))
+               return; /* already being destroyed */
+
        event_node = qede_rdma_get_free_event_node(edev);
        if (!event_node)
-               return;
+               goto out;
 
        event_node->event = event;
        event_node->ptr = edev;
 
        INIT_WORK(&event_node->work, qede_rdma_handle_event);
        queue_work(edev->rdma_info.rdma_wq, &event_node->work);
+
+out:
+       kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
 }
 
 void qede_rdma_dev_event_open(struct qede_dev *edev)
index 06de59521fc4a5e0d8861672525ab39406f98f18..fbf4cbcf1a6544b7fca722721bb94f1579493447 100644 (file)
 #include "rmnet_vnd.h"
 #include "rmnet_private.h"
 
-/* Locking scheme -
- * The shared resource which needs to be protected is realdev->rx_handler_data.
- * For the writer path, this is using rtnl_lock(). The writer paths are
- * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These
- * paths are already called with rtnl_lock() acquired in. There is also an
- * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For
- * dereference here, we will need to use rtnl_dereference(). Dev list writing
- * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link().
- * For the reader path, the real_dev->rx_handler_data is called in the TX / RX
- * path. We only need rcu_read_lock() for these scenarios. In these cases,
- * the rcu_read_lock() is held in __dev_queue_xmit() and
- * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl()
- * to get the relevant information. For dev list reading, we again acquire
- * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu().
- * We also use unregister_netdevice_many() to free all rmnet devices in
- * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in
- * same context.
- */
-
 /* Local Definitions and Declarations */
 
 static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = {
@@ -51,9 +32,10 @@ rmnet_get_port_rtnl(const struct net_device *real_dev)
        return rtnl_dereference(real_dev->rx_handler_data);
 }
 
-static int rmnet_unregister_real_device(struct net_device *real_dev,
-                                       struct rmnet_port *port)
+static int rmnet_unregister_real_device(struct net_device *real_dev)
 {
+       struct rmnet_port *port = rmnet_get_port_rtnl(real_dev);
+
        if (port->nr_rmnet_devs)
                return -EINVAL;
 
@@ -61,9 +43,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
 
        kfree(port);
 
-       /* release reference on real_dev */
-       dev_put(real_dev);
-
        netdev_dbg(real_dev, "Removed from rmnet\n");
        return 0;
 }
@@ -89,9 +68,6 @@ static int rmnet_register_real_device(struct net_device *real_dev)
                return -EBUSY;
        }
 
-       /* hold on to real dev for MAP data */
-       dev_hold(real_dev);
-
        for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
                INIT_HLIST_HEAD(&port->muxed_ep[entry]);
 
@@ -99,28 +75,33 @@ static int rmnet_register_real_device(struct net_device *real_dev)
        return 0;
 }
 
-static void rmnet_unregister_bridge(struct net_device *dev,
-                                   struct rmnet_port *port)
+static void rmnet_unregister_bridge(struct rmnet_port *port)
 {
-       struct rmnet_port *bridge_port;
-       struct net_device *bridge_dev;
+       struct net_device *bridge_dev, *real_dev, *rmnet_dev;
+       struct rmnet_port *real_port;
 
        if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
                return;
 
-       /* bridge slave handling */
+       rmnet_dev = port->rmnet_dev;
        if (!port->nr_rmnet_devs) {
-               bridge_dev = port->bridge_ep;
+               /* bridge device */
+               real_dev = port->bridge_ep;
+               bridge_dev = port->dev;
 
-               bridge_port = rmnet_get_port_rtnl(bridge_dev);
-               bridge_port->bridge_ep = NULL;
-               bridge_port->rmnet_mode = RMNET_EPMODE_VND;
+               real_port = rmnet_get_port_rtnl(real_dev);
+               real_port->bridge_ep = NULL;
+               real_port->rmnet_mode = RMNET_EPMODE_VND;
        } else {
+               /* real device */
                bridge_dev = port->bridge_ep;
 
-               bridge_port = rmnet_get_port_rtnl(bridge_dev);
-               rmnet_unregister_real_device(bridge_dev, bridge_port);
+               port->bridge_ep = NULL;
+               port->rmnet_mode = RMNET_EPMODE_VND;
        }
+
+       netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
+       rmnet_unregister_real_device(bridge_dev);
 }
 
 static int rmnet_newlink(struct net *src_net, struct net_device *dev,
@@ -135,6 +116,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
        int err = 0;
        u16 mux_id;
 
+       if (!tb[IFLA_LINK]) {
+               NL_SET_ERR_MSG_MOD(extack, "link not specified");
+               return -EINVAL;
+       }
+
        real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
        if (!real_dev || !dev)
                return -ENODEV;
@@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
        if (err)
                goto err1;
 
+       err = netdev_upper_dev_link(real_dev, dev, extack);
+       if (err < 0)
+               goto err2;
+
        port->rmnet_mode = mode;
+       port->rmnet_dev = dev;
 
        hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
 
@@ -173,8 +164,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 
        return 0;
 
+err2:
+       unregister_netdevice(dev);
+       rmnet_vnd_dellink(mux_id, port, ep);
 err1:
-       rmnet_unregister_real_device(real_dev, port);
+       rmnet_unregister_real_device(real_dev);
 err0:
        kfree(ep);
        return err;
@@ -183,77 +177,74 @@ err0:
 static void rmnet_dellink(struct net_device *dev, struct list_head *head)
 {
        struct rmnet_priv *priv = netdev_priv(dev);
-       struct net_device *real_dev;
+       struct net_device *real_dev, *bridge_dev;
+       struct rmnet_port *real_port, *bridge_port;
        struct rmnet_endpoint *ep;
-       struct rmnet_port *port;
-       u8 mux_id;
+       u8 mux_id = priv->mux_id;
 
        real_dev = priv->real_dev;
 
-       if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+       if (!rmnet_is_real_dev_registered(real_dev))
                return;
 
-       port = rmnet_get_port_rtnl(real_dev);
-
-       mux_id = rmnet_vnd_get_mux(dev);
+       real_port = rmnet_get_port_rtnl(real_dev);
+       bridge_dev = real_port->bridge_ep;
+       if (bridge_dev) {
+               bridge_port = rmnet_get_port_rtnl(bridge_dev);
+               rmnet_unregister_bridge(bridge_port);
+       }
 
-       ep = rmnet_get_endpoint(port, mux_id);
+       ep = rmnet_get_endpoint(real_port, mux_id);
        if (ep) {
                hlist_del_init_rcu(&ep->hlnode);
-               rmnet_unregister_bridge(dev, port);
-               rmnet_vnd_dellink(mux_id, port, ep);
+               rmnet_vnd_dellink(mux_id, real_port, ep);
                kfree(ep);
        }
-       rmnet_unregister_real_device(real_dev, port);
 
+       netdev_upper_dev_unlink(real_dev, dev);
+       rmnet_unregister_real_device(real_dev);
        unregister_netdevice_queue(dev, head);
 }
 
-static void rmnet_force_unassociate_device(struct net_device *dev)
+static void rmnet_force_unassociate_device(struct net_device *real_dev)
 {
-       struct net_device *real_dev = dev;
        struct hlist_node *tmp_ep;
        struct rmnet_endpoint *ep;
        struct rmnet_port *port;
        unsigned long bkt_ep;
        LIST_HEAD(list);
 
-       if (!rmnet_is_real_dev_registered(real_dev))
-               return;
-
-       ASSERT_RTNL();
-
-       port = rmnet_get_port_rtnl(dev);
-
-       rcu_read_lock();
-       rmnet_unregister_bridge(dev, port);
-
-       hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
-               unregister_netdevice_queue(ep->egress_dev, &list);
-               rmnet_vnd_dellink(ep->mux_id, port, ep);
+       port = rmnet_get_port_rtnl(real_dev);
 
-               hlist_del_init_rcu(&ep->hlnode);
-               kfree(ep);
+       if (port->nr_rmnet_devs) {
+               /* real device */
+               rmnet_unregister_bridge(port);
+               hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
+                       unregister_netdevice_queue(ep->egress_dev, &list);
+                       netdev_upper_dev_unlink(real_dev, ep->egress_dev);
+                       rmnet_vnd_dellink(ep->mux_id, port, ep);
+                       hlist_del_init_rcu(&ep->hlnode);
+                       kfree(ep);
+               }
+               rmnet_unregister_real_device(real_dev);
+               unregister_netdevice_many(&list);
+       } else {
+               rmnet_unregister_bridge(port);
        }
-
-       rcu_read_unlock();
-       unregister_netdevice_many(&list);
-
-       rmnet_unregister_real_device(real_dev, port);
 }
 
 static int rmnet_config_notify_cb(struct notifier_block *nb,
                                  unsigned long event, void *data)
 {
-       struct net_device *dev = netdev_notifier_info_to_dev(data);
+       struct net_device *real_dev = netdev_notifier_info_to_dev(data);
 
-       if (!dev)
+       if (!rmnet_is_real_dev_registered(real_dev))
                return NOTIFY_DONE;
 
        switch (event) {
        case NETDEV_UNREGISTER:
-               netdev_dbg(dev, "Kernel unregister\n");
-               rmnet_force_unassociate_device(dev);
+               netdev_dbg(real_dev, "Kernel unregister\n");
+               rmnet_force_unassociate_device(real_dev);
                break;
 
        default:
@@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
        if (!dev)
                return -ENODEV;
 
-       real_dev = __dev_get_by_index(dev_net(dev),
-                                     nla_get_u32(tb[IFLA_LINK]));
-
-       if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+       real_dev = priv->real_dev;
+       if (!rmnet_is_real_dev_registered(real_dev))
                return -ENODEV;
 
        port = rmnet_get_port_rtnl(real_dev);
 
        if (data[IFLA_RMNET_MUX_ID]) {
                mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
+               if (rmnet_get_endpoint(port, mux_id)) {
+                       NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
+                       return -EINVAL;
+               }
                ep = rmnet_get_endpoint(port, priv->mux_id);
                if (!ep)
                        return -ENODEV;
@@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
        .fill_info      = rmnet_fill_info,
 };
 
-/* Needs either rcu_read_lock() or rtnl lock */
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev)
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev)
 {
        if (rmnet_is_real_dev_registered(real_dev))
-               return rcu_dereference_rtnl(real_dev->rx_handler_data);
+               return rcu_dereference_bh(real_dev->rx_handler_data);
        else
                return NULL;
 }
@@ -409,7 +401,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        struct rmnet_port *port, *slave_port;
        int err;
 
-       port = rmnet_get_port(real_dev);
+       port = rmnet_get_port_rtnl(real_dev);
 
        /* If there is more than one rmnet dev attached, its probably being
         * used for muxing. Skip the briding in that case
@@ -417,6 +409,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        if (port->nr_rmnet_devs > 1)
                return -EINVAL;
 
+       if (port->rmnet_mode != RMNET_EPMODE_VND)
+               return -EINVAL;
+
        if (rmnet_is_real_dev_registered(slave_dev))
                return -EBUSY;
 
@@ -424,9 +419,17 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        if (err)
                return -EBUSY;
 
-       slave_port = rmnet_get_port(slave_dev);
+       err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
+                                          extack);
+       if (err) {
+               rmnet_unregister_real_device(slave_dev);
+               return err;
+       }
+
+       slave_port = rmnet_get_port_rtnl(slave_dev);
        slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
        slave_port->bridge_ep = real_dev;
+       slave_port->rmnet_dev = rmnet_dev;
 
        port->rmnet_mode = RMNET_EPMODE_BRIDGE;
        port->bridge_ep = slave_dev;
@@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
 int rmnet_del_bridge(struct net_device *rmnet_dev,
                     struct net_device *slave_dev)
 {
-       struct rmnet_priv *priv = netdev_priv(rmnet_dev);
-       struct net_device *real_dev = priv->real_dev;
-       struct rmnet_port *port, *slave_port;
+       struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
 
-       port = rmnet_get_port(real_dev);
-       port->rmnet_mode = RMNET_EPMODE_VND;
-       port->bridge_ep = NULL;
-
-       slave_port = rmnet_get_port(slave_dev);
-       rmnet_unregister_real_device(slave_dev, slave_port);
+       rmnet_unregister_bridge(port);
 
        netdev_dbg(slave_dev, "removed from rmnet as slave\n");
        return 0;
@@ -473,8 +469,8 @@ static int __init rmnet_init(void)
 
 static void __exit rmnet_exit(void)
 {
-       unregister_netdevice_notifier(&rmnet_dev_notifier);
        rtnl_link_unregister(&rmnet_link_ops);
+       unregister_netdevice_notifier(&rmnet_dev_notifier);
 }
 
 module_init(rmnet_init)
index cd0a6bcbe74ade8247a428345615240faa6d9169..be515982d6286e8d9ca676e8a316b1f8e4606765 100644 (file)
@@ -28,6 +28,7 @@ struct rmnet_port {
        u8 rmnet_mode;
        struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
        struct net_device *bridge_ep;
+       struct net_device *rmnet_dev;
 };
 
 extern struct rtnl_link_ops rmnet_link_ops;
@@ -65,7 +66,7 @@ struct rmnet_priv {
        struct rmnet_priv_stats stats;
 };
 
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev);
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev);
 struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id);
 int rmnet_add_bridge(struct net_device *rmnet_dev,
                     struct net_device *slave_dev,
index 1b74bc16040274f21432aba798898e688e716eb5..29a7bfa2584dc95b05fbcc7de61a5c912739b435 100644 (file)
@@ -159,6 +159,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 static void
 rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev)
 {
+       if (skb_mac_header_was_set(skb))
+               skb_push(skb, skb->mac_len);
+
        if (bridge_dev) {
                skb->dev = bridge_dev;
                dev_queue_xmit(skb);
@@ -184,7 +187,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
                return RX_HANDLER_PASS;
 
        dev = skb->dev;
-       port = rmnet_get_port(dev);
+       port = rmnet_get_port_rcu(dev);
 
        switch (port->rmnet_mode) {
        case RMNET_EPMODE_VND:
@@ -217,7 +220,7 @@ void rmnet_egress_handler(struct sk_buff *skb)
        skb->dev = priv->real_dev;
        mux_id = priv->mux_id;
 
-       port = rmnet_get_port(skb->dev);
+       port = rmnet_get_port_rcu(skb->dev);
        if (!port)
                goto drop;
 
index 509dfc895a33ee2d0d5395b18d69bd998468dc1a..26ad40f19c64caae7476c58fb24cf7d3efe4cd13 100644 (file)
@@ -266,14 +266,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
        return 0;
 }
 
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev)
-{
-       struct rmnet_priv *priv;
-
-       priv = netdev_priv(rmnet_dev);
-       return priv->mux_id;
-}
-
 int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
 {
        netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
index 54cbaf3c3bc4309347b5966548a3f4c49d5644f2..14d77c709d4adf63e93ba3220d2818873b2d6bab 100644 (file)
@@ -16,6 +16,5 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
                      struct rmnet_endpoint *ep);
 void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev);
 void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev);
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev);
 void rmnet_vnd_setup(struct net_device *dev);
 #endif /* _RMNET_VND_H_ */
index af15a737c675611919a65d5394447900dbac3f26..59b4f16896a81e561ce6df586c255b6a8639bf4e 100644 (file)
@@ -560,13 +560,45 @@ efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx,
                                    u32 nic_major, u32 nic_minor,
                                    s32 correction)
 {
+       u32 sync_timestamp;
        ktime_t kt = { 0 };
+       s16 delta;
 
        if (!(nic_major & 0x80000000)) {
                WARN_ON_ONCE(nic_major >> 16);
-               /* Use the top bits from the latest sync event. */
-               nic_major &= 0xffff;
-               nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000);
+
+               /* Medford provides 48 bits of timestamp, so we must get the top
+                * 16 bits from the timesync event state.
+                *
+                * We only have the lower 16 bits of the time now, but we do
+                * have a full resolution timestamp at some point in past. As
+                * long as the difference between the (real) now and the sync
+                * is less than 2^15, then we can reconstruct the difference
+                * between those two numbers using only the lower 16 bits of
+                * each.
+                *
+                * Put another way
+                *
+                * a - b = ((a mod k) - b) mod k
+                *
+                * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know
+                * (a mod k) and b, so can calculate the delta, a - b.
+                *
+                */
+               sync_timestamp = last_sync_timestamp_major(efx);
+
+               /* Because delta is s16 this does an implicit mask down to
+                * 16 bits which is what we need, assuming
+                * MEDFORD_TX_SECS_EVENT_BITS is 16. delta is signed so that
+                * we can deal with the (unlikely) case of sync timestamps
+                * arriving from the future.
+                */
+               delta = nic_major - sync_timestamp;
+
+               /* Recover the fully specified time now, by applying the offset
+                * to the (fully specified) sync time.
+                */
+               nic_major = sync_timestamp + delta;
 
                kt = ptp->nic_to_kernel_time(nic_major, nic_minor,
                                             correction);
index 5836b21edd7ed7b54604acb60f0d95501c1169d3..7da18c9afa01d2843d431f47430d58a6df171e05 100644 (file)
@@ -4405,6 +4405,8 @@ static void stmmac_init_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
+       rtnl_lock();
+
        /* Create per netdev entries */
        priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
 
@@ -4416,14 +4418,13 @@ static void stmmac_init_fs(struct net_device *dev)
        debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev,
                            &stmmac_dma_cap_fops);
 
-       register_netdevice_notifier(&stmmac_notifier);
+       rtnl_unlock();
 }
 
 static void stmmac_exit_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(priv->dbgfs_dir);
 }
 #endif /* CONFIG_DEBUG_FS */
@@ -4940,14 +4941,14 @@ int stmmac_dvr_remove(struct device *dev)
 
        netdev_info(priv->dev, "%s: removing driver", __func__);
 
-#ifdef CONFIG_DEBUG_FS
-       stmmac_exit_fs(ndev);
-#endif
        stmmac_stop_all_dma(priv);
 
        stmmac_mac_set(priv, priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
+#ifdef CONFIG_DEBUG_FS
+       stmmac_exit_fs(ndev);
+#endif
        phylink_destroy(priv->phylink);
        if (priv->plat->stmmac_rst)
                reset_control_assert(priv->plat->stmmac_rst);
@@ -5166,6 +5167,7 @@ static int __init stmmac_init(void)
        /* Create debugfs main directory if it doesn't exist yet */
        if (!stmmac_fs_dir)
                stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
+       register_netdevice_notifier(&stmmac_notifier);
 #endif
 
        return 0;
@@ -5174,6 +5176,7 @@ static int __init stmmac_init(void)
 static void __exit stmmac_exit(void)
 {
 #ifdef CONFIG_DEBUG_FS
+       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(stmmac_fs_dir);
 #endif
 }
index 276292bca334d853aace75bbefcfc95477e0491d..53fb8141f1a673e7e2be3a25d0873d8d26451eab 100644 (file)
@@ -375,10 +375,14 @@ struct temac_local {
        int tx_bd_next;
        int tx_bd_tail;
        int rx_bd_ci;
+       int rx_bd_tail;
 
        /* DMA channel control setup */
        u32 tx_chnl_ctrl;
        u32 rx_chnl_ctrl;
+       u8 coalesce_count_rx;
+
+       struct delayed_work restart_work;
 };
 
 /* Wrappers for temac_ior()/temac_iow() function pointers above */
index 6f11f52c9a9ed31a41722e5737ab546b64400517..9461acec6f70f8a0e9d7de88444dd573cc0c8551 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/ip.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <linux/processor.h>
 #include <linux/platform_data/xilinx-ll-temac.h>
@@ -367,6 +368,8 @@ static int temac_dma_bd_init(struct net_device *ndev)
                skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                              XTE_MAX_JUMBO_FRAME_SIZE,
                                              DMA_FROM_DEVICE);
+               if (dma_mapping_error(ndev->dev.parent, skb_dma_addr))
+                       goto out;
                lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr);
                lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
                lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
@@ -387,12 +390,13 @@ static int temac_dma_bd_init(struct net_device *ndev)
        lp->tx_bd_next = 0;
        lp->tx_bd_tail = 0;
        lp->rx_bd_ci = 0;
+       lp->rx_bd_tail = RX_BD_NUM - 1;
 
        /* Enable RX DMA transfers */
        wmb();
        lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
        lp->dma_out(lp, RX_TAILDESC_PTR,
-                      lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+                      lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail));
 
        /* Prepare for TX DMA transfer */
        lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
@@ -788,6 +792,9 @@ static void temac_start_xmit_done(struct net_device *ndev)
                stat = be32_to_cpu(cur_p->app0);
        }
 
+       /* Matches barrier in temac_start_xmit */
+       smp_mb();
+
        netif_wake_queue(ndev);
 }
 
@@ -830,9 +837,19 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 
        if (temac_check_tx_bd_space(lp, num_frag + 1)) {
-               if (!netif_queue_stopped(ndev))
-                       netif_stop_queue(ndev);
-               return NETDEV_TX_BUSY;
+               if (netif_queue_stopped(ndev))
+                       return NETDEV_TX_BUSY;
+
+               netif_stop_queue(ndev);
+
+               /* Matches barrier in temac_start_xmit_done */
+               smp_mb();
+
+               /* Space might have just been freed - check again */
+               if (temac_check_tx_bd_space(lp, num_frag))
+                       return NETDEV_TX_BUSY;
+
+               netif_wake_queue(ndev);
        }
 
        cur_p->app0 = 0;
@@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                      skb_headlen(skb), DMA_TO_DEVICE);
        cur_p->len = cpu_to_be32(skb_headlen(skb));
+       if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) {
+               dev_kfree_skb_any(skb);
+               ndev->stats.tx_dropped++;
+               return NETDEV_TX_OK;
+       }
        cur_p->phys = cpu_to_be32(skb_dma_addr);
        ptr_to_txbd((void *)skb, cur_p);
 
        for (ii = 0; ii < num_frag; ii++) {
-               lp->tx_bd_tail++;
-               if (lp->tx_bd_tail >= TX_BD_NUM)
+               if (++lp->tx_bd_tail >= TX_BD_NUM)
                        lp->tx_bd_tail = 0;
 
                cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
@@ -863,6 +884,27 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                              skb_frag_address(frag),
                                              skb_frag_size(frag),
                                              DMA_TO_DEVICE);
+               if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) {
+                       if (--lp->tx_bd_tail < 0)
+                               lp->tx_bd_tail = TX_BD_NUM - 1;
+                       cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+                       while (--ii >= 0) {
+                               --frag;
+                               dma_unmap_single(ndev->dev.parent,
+                                                be32_to_cpu(cur_p->phys),
+                                                skb_frag_size(frag),
+                                                DMA_TO_DEVICE);
+                               if (--lp->tx_bd_tail < 0)
+                                       lp->tx_bd_tail = TX_BD_NUM - 1;
+                               cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+                       }
+                       dma_unmap_single(ndev->dev.parent,
+                                        be32_to_cpu(cur_p->phys),
+                                        skb_headlen(skb), DMA_TO_DEVICE);
+                       dev_kfree_skb_any(skb);
+                       ndev->stats.tx_dropped++;
+                       return NETDEV_TX_OK;
+               }
                cur_p->phys = cpu_to_be32(skb_dma_addr);
                cur_p->len = cpu_to_be32(skb_frag_size(frag));
                cur_p->app0 = 0;
@@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+static int ll_temac_recv_buffers_available(struct temac_local *lp)
+{
+       int available;
+
+       if (!lp->rx_skb[lp->rx_bd_ci])
+               return 0;
+       available = 1 + lp->rx_bd_tail - lp->rx_bd_ci;
+       if (available <= 0)
+               available += RX_BD_NUM;
+       return available;
+}
 
 static void ll_temac_recv(struct net_device *ndev)
 {
        struct temac_local *lp = netdev_priv(ndev);
-       struct sk_buff *skb, *new_skb;
-       unsigned int bdstat;
-       struct cdmac_bd *cur_p;
-       dma_addr_t tail_p, skb_dma_addr;
-       int length;
        unsigned long flags;
+       int rx_bd;
+       bool update_tail = false;
 
        spin_lock_irqsave(&lp->rx_lock, flags);
 
-       tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
-       cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-
-       bdstat = be32_to_cpu(cur_p->app0);
-       while ((bdstat & STS_CTRL_APP0_CMPLT)) {
+       /* Process all received buffers, passing them on network
+        * stack.  After this, the buffer descriptors will be in an
+        * un-allocated stage, where no skb is allocated for it, and
+        * they are therefore not available for TEMAC/DMA.
+        */
+       do {
+               struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci];
+               struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci];
+               unsigned int bdstat = be32_to_cpu(bd->app0);
+               int length;
+
+               /* While this should not normally happen, we can end
+                * here when GFP_ATOMIC allocations fail, and we
+                * therefore have un-allocated buffers.
+                */
+               if (!skb)
+                       break;
 
-               skb = lp->rx_skb[lp->rx_bd_ci];
-               length = be32_to_cpu(cur_p->app4) & 0x3FFF;
+               /* Loop over all completed buffer descriptors */
+               if (!(bdstat & STS_CTRL_APP0_CMPLT))
+                       break;
 
-               dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys),
+               dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys),
                                 XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
+               /* The buffer is not valid for DMA anymore */
+               bd->phys = 0;
+               bd->len = 0;
 
+               length = be32_to_cpu(bd->app4) & 0x3FFF;
                skb_put(skb, length);
                skb->protocol = eth_type_trans(skb, ndev);
                skb_checksum_none_assert(skb);
@@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev)
                         * (back) for proper IP checksum byte order
                         * (be16).
                         */
-                       skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF);
+                       skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF);
                        skb->ip_summed = CHECKSUM_COMPLETE;
                }
 
                if (!skb_defer_rx_timestamp(skb))
                        netif_rx(skb);
+               /* The skb buffer is now owned by network stack above */
+               lp->rx_skb[lp->rx_bd_ci] = NULL;
 
                ndev->stats.rx_packets++;
                ndev->stats.rx_bytes += length;
 
-               new_skb = netdev_alloc_skb_ip_align(ndev,
-                                               XTE_MAX_JUMBO_FRAME_SIZE);
-               if (!new_skb) {
-                       spin_unlock_irqrestore(&lp->rx_lock, flags);
-                       return;
+               rx_bd = lp->rx_bd_ci;
+               if (++lp->rx_bd_ci >= RX_BD_NUM)
+                       lp->rx_bd_ci = 0;
+       } while (rx_bd != lp->rx_bd_tail);
+
+       /* DMA operations will halt when the last buffer descriptor is
+        * processed (ie. the one pointed to by RX_TAILDESC_PTR).
+        * When that happens, no more interrupt events will be
+        * generated.  No IRQ_COAL or IRQ_DLY, and not even an
+        * IRQ_ERR.  To avoid stalling, we schedule a delayed work
+        * when there is a potential risk of that happening.  The work
+        * will call this function, and thus re-schedule itself until
+        * enough buffers are available again.
+        */
+       if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx)
+               schedule_delayed_work(&lp->restart_work, HZ / 1000);
+
+       /* Allocate new buffers for those buffer descriptors that were
+        * passed to network stack.  Note that GFP_ATOMIC allocations
+        * can fail (e.g. when a larger burst of GFP_ATOMIC
+        * allocations occurs), so while we try to allocate all
+        * buffers in the same interrupt where they were processed, we
+        * continue with what we could get in case of allocation
+        * failure.  Allocation of remaining buffers will be retried
+        * in following calls.
+        */
+       while (1) {
+               struct sk_buff *skb;
+               struct cdmac_bd *bd;
+               dma_addr_t skb_dma_addr;
+
+               rx_bd = lp->rx_bd_tail + 1;
+               if (rx_bd >= RX_BD_NUM)
+                       rx_bd = 0;
+               bd = &lp->rx_bd_v[rx_bd];
+
+               if (bd->phys)
+                       break;  /* All skb's allocated */
+
+               skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE);
+               if (!skb) {
+                       dev_warn(&ndev->dev, "skb alloc failed\n");
+                       break;
                }
 
-               cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
-               skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data,
+               skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                              XTE_MAX_JUMBO_FRAME_SIZE,
                                              DMA_FROM_DEVICE);
-               cur_p->phys = cpu_to_be32(skb_dma_addr);
-               cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
-               lp->rx_skb[lp->rx_bd_ci] = new_skb;
+               if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent,
+                                                  skb_dma_addr))) {
+                       dev_kfree_skb_any(skb);
+                       break;
+               }
 
-               lp->rx_bd_ci++;
-               if (lp->rx_bd_ci >= RX_BD_NUM)
-                       lp->rx_bd_ci = 0;
+               bd->phys = cpu_to_be32(skb_dma_addr);
+               bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
+               bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
+               lp->rx_skb[rx_bd] = skb;
 
-               cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-               bdstat = be32_to_cpu(cur_p->app0);
+               lp->rx_bd_tail = rx_bd;
+               update_tail = true;
+       }
+
+       /* Move tail pointer when buffers have been allocated */
+       if (update_tail) {
+               lp->dma_out(lp, RX_TAILDESC_PTR,
+                       lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail);
        }
-       lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
 
        spin_unlock_irqrestore(&lp->rx_lock, flags);
 }
 
+/* Function scheduled to ensure a restart in case of DMA halt
+ * condition caused by running out of buffer descriptors.
+ */
+static void ll_temac_restart_work_func(struct work_struct *work)
+{
+       struct temac_local *lp = container_of(work, struct temac_local,
+                                             restart_work.work);
+       struct net_device *ndev = lp->ndev;
+
+       ll_temac_recv(ndev);
+}
+
 static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
 {
        struct net_device *ndev = _ndev;
@@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev)
 
        dev_dbg(&ndev->dev, "temac_close()\n");
 
+       cancel_delayed_work_sync(&lp->restart_work);
+
        free_irq(lp->tx_irq, ndev);
        free_irq(lp->rx_irq, ndev);
 
@@ -1173,6 +1301,7 @@ static int temac_probe(struct platform_device *pdev)
        lp->dev = &pdev->dev;
        lp->options = XTE_OPTION_DEFAULTS;
        spin_lock_init(&lp->rx_lock);
+       INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func);
 
        /* Setup mutex for synchronization of indirect register access */
        if (pdata) {
@@ -1279,6 +1408,7 @@ static int temac_probe(struct platform_device *pdev)
                 */
                lp->tx_chnl_ctrl = 0x10220000;
                lp->rx_chnl_ctrl = 0xff070000;
+               lp->coalesce_count_rx = 0x07;
 
                /* Finished with the DMA node; drop the reference */
                of_node_put(dma_np);
@@ -1310,11 +1440,14 @@ static int temac_probe(struct platform_device *pdev)
                                (pdata->tx_irq_count << 16);
                else
                        lp->tx_chnl_ctrl = 0x10220000;
-               if (pdata->rx_irq_timeout || pdata->rx_irq_count)
+               if (pdata->rx_irq_timeout || pdata->rx_irq_count) {
                        lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) |
                                (pdata->rx_irq_count << 16);
-               else
+                       lp->coalesce_count_rx = pdata->rx_irq_count;
+               } else {
                        lp->rx_chnl_ctrl = 0xff070000;
+                       lp->coalesce_count_rx = 0x07;
+               }
        }
 
        /* Error handle returned DMA RX and TX interrupts */
index ae3f3084c2ed29bd19522f27f51283275310beaa..1b320bcf150a4ddc91204e21b3bac4a1140cad5e 100644 (file)
@@ -99,7 +99,7 @@ static struct netvsc_device *alloc_net_device(void)
 
        init_waitqueue_head(&net_device->wait_drain);
        net_device->destroy = false;
-       net_device->tx_disable = false;
+       net_device->tx_disable = true;
 
        net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
        net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
index 65e12cb07f453fb0472d5bb527748d6ee8a18f92..2c0a24c606fc7dc49cbf247d22e8082f2cad2013 100644 (file)
@@ -1068,6 +1068,7 @@ static int netvsc_attach(struct net_device *ndev,
        }
 
        /* In any case device is now ready */
+       nvdev->tx_disable = false;
        netif_device_attach(ndev);
 
        /* Note: enable and attach happen when sub-channels setup */
@@ -2476,6 +2477,8 @@ static int netvsc_probe(struct hv_device *dev,
        else
                net->max_mtu = ETH_DATA_LEN;
 
+       nvdev->tx_disable = false;
+
        ret = register_netdevice(net);
        if (ret != 0) {
                pr_err("Unable to register netdev.\n");
index 7d68b28bb8938de99fb2f979cd33df9975e82903..a62229a8b1a41eca2de85cf2e3574ea31953eb95 100644 (file)
@@ -410,7 +410,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
        struct device_node *np = phydev->mdio.dev.of_node;
        int ret;
 
-       /* Aneg firsly. */
+       /* Aneg firstly. */
        ret = genphy_config_aneg(phydev);
 
        /* Then we can set up the delay. */
@@ -463,7 +463,7 @@ static int bcm54616s_config_aneg(struct phy_device *phydev)
 {
        int ret;
 
-       /* Aneg firsly. */
+       /* Aneg firstly. */
        if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
                ret = genphy_c37_config_aneg(phydev);
        else
index 28e33ece4ce17aa132a214d2be32761bf3827cb4..9a8badafea8ac95e123d14694437f60bc44eb453 100644 (file)
@@ -1306,6 +1306,9 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
                }
        }
 
+       if (!(status & MII_M1011_PHY_STATUS_RESOLVED))
+               return 0;
+
        if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
                phydev->duplex = DUPLEX_FULL;
        else
@@ -1365,6 +1368,8 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
        linkmode_zero(phydev->lp_advertising);
        phydev->pause = 0;
        phydev->asym_pause = 0;
+       phydev->speed = SPEED_UNKNOWN;
+       phydev->duplex = DUPLEX_UNKNOWN;
 
        if (phydev->autoneg == AUTONEG_ENABLE)
                err = marvell_read_status_page_an(phydev, fiber, status);
index 7e9975d2506691ee77f319a6fb0741596a8e1bde..f1ded03f0229b1460ba992166434f3290ec23c37 100644 (file)
@@ -178,6 +178,23 @@ static int iproc_mdio_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+int iproc_mdio_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct iproc_mdio_priv *priv = platform_get_drvdata(pdev);
+
+       /* restore the mii clock configuration */
+       iproc_mdio_config_clk(priv->base);
+
+       return 0;
+}
+
+static const struct dev_pm_ops iproc_mdio_pm_ops = {
+       .resume = iproc_mdio_resume
+};
+#endif /* CONFIG_PM_SLEEP */
+
 static const struct of_device_id iproc_mdio_of_match[] = {
        { .compatible = "brcm,iproc-mdio", },
        { /* sentinel */ },
@@ -188,6 +205,9 @@ static struct platform_driver iproc_mdio_driver = {
        .driver = {
                .name = "iproc-mdio",
                .of_match_table = iproc_mdio_of_match,
+#ifdef CONFIG_PM_SLEEP
+               .pm = &iproc_mdio_pm_ops,
+#endif
        },
        .probe = iproc_mdio_probe,
        .remove = iproc_mdio_remove,
index 937ac7da278944c3d9c39cd5b16a879ea116b2b6..f686f40f6bdcceb1807275f02dc57abd84c666a4 100644 (file)
@@ -345,11 +345,11 @@ enum macsec_bank {
                                BIT(VSC8531_FORCE_LED_OFF) | \
                                BIT(VSC8531_FORCE_LED_ON))
 
-#define MSCC_VSC8584_REVB_INT8051_FW           "mscc_vsc8584_revb_int8051_fb48.bin"
+#define MSCC_VSC8584_REVB_INT8051_FW           "microchip/mscc_vsc8584_revb_int8051_fb48.bin"
 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR        0xe800
 #define MSCC_VSC8584_REVB_INT8051_FW_CRC       0xfb48
 
-#define MSCC_VSC8574_REVB_INT8051_FW           "mscc_vsc8574_revb_int8051_29e8.bin"
+#define MSCC_VSC8574_REVB_INT8051_FW           "microchip/mscc_vsc8574_revb_int8051_29e8.bin"
 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR        0x4000
 #define MSCC_VSC8574_REVB_INT8051_FW_CRC       0x29e8
 
index a1caeee1223617dab21b488858b14b5d0ef2aa2a..dd2e23fb67c068674144f5c1afc97ca682bb6b8f 100644 (file)
@@ -167,7 +167,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
  */
 int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
 {
-       int ret = 0;
+       int ret;
 
        if (!restart) {
                /* Configure and restart aneg if it wasn't set before */
@@ -180,9 +180,9 @@ int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
        }
 
        if (restart)
-               ret = genphy_c45_restart_aneg(phydev);
+               return genphy_c45_restart_aneg(phydev);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
 
index 6a5056e0ae77578cc44006eaec2fef72cf646717..c8b0c34030d32cdf7cac3acfdc50903da5eecf0f 100644 (file)
@@ -247,7 +247,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
         * MDIO bus driver and clock gated at this point.
         */
        if (!netdev)
-               return !phydev->suspended;
+               goto out;
 
        if (netdev->wol_enabled)
                return false;
@@ -267,7 +267,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
        if (device_may_wakeup(&netdev->dev))
                return false;
 
-       return true;
+out:
+       return !phydev->suspended;
 }
 
 static int mdio_bus_phy_suspend(struct device *dev)
@@ -1792,7 +1793,7 @@ EXPORT_SYMBOL(genphy_restart_aneg);
  */
 int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
 {
-       int ret = 0;
+       int ret;
 
        if (!restart) {
                /* Advertisement hasn't changed, but maybe aneg was never on to
@@ -1807,9 +1808,9 @@ int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
        }
 
        if (restart)
-               ret = genphy_restart_aneg(phydev);
+               return genphy_restart_aneg(phydev);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(genphy_check_and_restart_aneg);
 
index 6f4d7ba8b1094eac73b0ea503bee81d9d976178c..babb01888b786c2e77c9d7b4844f44d31b9c7bce 100644 (file)
@@ -863,7 +863,10 @@ err_free_chan:
        tty->disc_data = NULL;
        clear_bit(SLF_INUSE, &sl->flags);
        sl_free_netdev(sl->dev);
+       /* do not call free_netdev before rtnl_unlock */
+       rtnl_unlock();
        free_netdev(sl->dev);
+       return err;
 
 err_exit:
        rtnl_unlock();
index 3b7a3b8a5e067c4676afc7b20cb65c2af0e356bc..5754bb6ca0eeccc129b16b3b9ff433d067d00e34 100644 (file)
@@ -337,6 +337,9 @@ static void qmi_wwan_netdev_setup(struct net_device *net)
                netdev_dbg(net, "mode: raw IP\n");
        } else if (!net->header_ops) { /* don't bother if already set */
                ether_setup(net);
+               /* Restoring min/max mtu values set originally by usbnet */
+               net->min_mtu = 0;
+               net->max_mtu = ETH_MAX_MTU;
                clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
                netdev_dbg(net, "mode: Ethernet\n");
        }
index 43db442b1373073eaf5e805cfe6cfee15875437a..cdc96968b0f4ba93c5e078f5ec46ace576f9d214 100644 (file)
@@ -258,6 +258,8 @@ static void wg_setup(struct net_device *dev)
        enum { WG_NETDEV_FEATURES = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
                                    NETIF_F_SG | NETIF_F_GSO |
                                    NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA };
+       const int overhead = MESSAGE_MINIMUM_LENGTH + sizeof(struct udphdr) +
+                            max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
 
        dev->netdev_ops = &netdev_ops;
        dev->hard_header_len = 0;
@@ -271,9 +273,8 @@ static void wg_setup(struct net_device *dev)
        dev->features |= WG_NETDEV_FEATURES;
        dev->hw_features |= WG_NETDEV_FEATURES;
        dev->hw_enc_features |= WG_NETDEV_FEATURES;
-       dev->mtu = ETH_DATA_LEN - MESSAGE_MINIMUM_LENGTH -
-                  sizeof(struct udphdr) -
-                  max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
+       dev->mtu = ETH_DATA_LEN - overhead;
+       dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead;
 
        SET_NETDEV_DEVTYPE(dev, &device_type);
 
index 9c6bab9c981f4a41d2bf008e0de739d2bd484c02..4a153894cee259504587f88e90e6ce78bfa68ea3 100644 (file)
@@ -118,10 +118,13 @@ static void wg_receive_handshake_packet(struct wg_device *wg,
 
        under_load = skb_queue_len(&wg->incoming_handshakes) >=
                     MAX_QUEUED_INCOMING_HANDSHAKES / 8;
-       if (under_load)
+       if (under_load) {
                last_under_load = ktime_get_coarse_boottime_ns();
-       else if (last_under_load)
+       } else if (last_under_load) {
                under_load = !wg_birthdate_has_expired(last_under_load, 1);
+               if (!under_load)
+                       last_under_load = 0;
+       }
        mac_state = wg_cookie_validate_packet(&wg->cookie_checker, skb,
                                              under_load);
        if ((under_load && mac_state == VALID_MAC_WITH_COOKIE) ||
index c13260563446079ae5d0fca896f1ddf64fdb4c65..7348c10cbae3db54bfcb31f23c2753185735f876 100644 (file)
@@ -143,16 +143,22 @@ static void keep_key_fresh(struct wg_peer *peer)
 
 static unsigned int calculate_skb_padding(struct sk_buff *skb)
 {
+       unsigned int padded_size, last_unit = skb->len;
+
+       if (unlikely(!PACKET_CB(skb)->mtu))
+               return ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE) - last_unit;
+
        /* We do this modulo business with the MTU, just in case the networking
         * layer gives us a packet that's bigger than the MTU. In that case, we
         * wouldn't want the final subtraction to overflow in the case of the
-        * padded_size being clamped.
+        * padded_size being clamped. Fortunately, that's very rarely the case,
+        * so we optimize for that not happening.
         */
-       unsigned int last_unit = skb->len % PACKET_CB(skb)->mtu;
-       unsigned int padded_size = ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE);
+       if (unlikely(last_unit > PACKET_CB(skb)->mtu))
+               last_unit %= PACKET_CB(skb)->mtu;
 
-       if (padded_size > PACKET_CB(skb)->mtu)
-               padded_size = PACKET_CB(skb)->mtu;
+       padded_size = min(PACKET_CB(skb)->mtu,
+                         ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE));
        return padded_size - last_unit;
 }
 
index 262f3b5c819d5a3c7c3b2691ddc510298dc4b31a..b0d6541582d312eeed1a5a25123cb27380cd038f 100644 (file)
@@ -432,7 +432,6 @@ void wg_socket_reinit(struct wg_device *wg, struct sock *new4,
                wg->incoming_port = ntohs(inet_sk(new4)->inet_sport);
        mutex_unlock(&wg->socket_update_lock);
        synchronize_rcu();
-       synchronize_net();
        sock_free(old4);
        sock_free(old6);
 }
index 720c89d6066ef5567ebb55b72bca566a0b8336e0..4ac8cb262559ce5401dbd6a28e7f09ce0298ded4 100644 (file)
@@ -225,6 +225,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
 
 out:
        gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
+       usleep_range(10000, 15000);
 }
 
 static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode)
index 2b83156efe3fff981404e56330ac377430f0f58c..b788870473e85d7d1c89493fce399ee37993b138 100644 (file)
@@ -682,7 +682,7 @@ static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
 static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
                                   struct nfc_target *target)
 {
-       pr_debug("supported protocol %d\b", target->supported_protocols);
+       pr_debug("supported protocol %d\n", target->supported_protocols);
        if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK |
                                        NFC_PROTO_ISO14443_B_MASK)) {
                return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
index ada59df642d2975f1fb7c806ea1d50c861dd66ec..a4d8c90ee7cc4b2d0f74e9a9a0de49a5e6916667 100644 (file)
@@ -1165,8 +1165,8 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl,
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
                unsigned int dword11, void *buffer, size_t buflen, u32 *result)
 {
+       union nvme_result res = { 0 };
        struct nvme_command c;
-       union nvme_result res;
        int ret;
 
        memset(&c, 0, sizeof(c));
index 797c18337d9621b24b63227f214222d20cf2ee3e..a11900cf3a365ba4d48531b17226a27524dc4bc9 100644 (file)
@@ -715,6 +715,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        }
 
        INIT_WORK(&ctrl->ana_work, nvme_ana_work);
+       kfree(ctrl->ana_log_buf);
        ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
        if (!ctrl->ana_log_buf) {
                error = -ENOMEM;
index 9c80f9f081496b09c8e17487624dec9008817863..d3f23d6254e47a4d1a2cfd53323a327aca17c013 100644 (file)
@@ -1078,9 +1078,9 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx)
 
        spin_lock(&nvmeq->cq_poll_lock);
        found = nvme_process_cq(nvmeq, &start, &end, -1);
+       nvme_complete_cqes(nvmeq, start, end);
        spin_unlock(&nvmeq->cq_poll_lock);
 
-       nvme_complete_cqes(nvmeq, start, end);
        return found;
 }
 
@@ -2747,6 +2747,18 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
                    (dmi_match(DMI_BOARD_NAME, "PRIME B350M-A") ||
                     dmi_match(DMI_BOARD_NAME, "PRIME Z370-A")))
                        return NVME_QUIRK_NO_APST;
+       } else if ((pdev->vendor == 0x144d && (pdev->device == 0xa801 ||
+                   pdev->device == 0xa808 || pdev->device == 0xa809)) ||
+                  (pdev->vendor == 0x1e0f && pdev->device == 0x0001)) {
+               /*
+                * Forcing to use host managed nvme power settings for
+                * lowest idle power with quick resume latency on
+                * Samsung and Toshiba SSDs based on suspend behavior
+                * on Coffee Lake board for LENOVO C640
+                */
+               if ((dmi_match(DMI_BOARD_VENDOR, "LENOVO")) &&
+                    dmi_match(DMI_BOARD_NAME, "LNVNB161216"))
+                       return NVME_QUIRK_SIMPLE_SUSPEND;
        }
 
        return 0;
@@ -3109,7 +3121,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
-       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
+               .driver_data = NVME_QUIRK_SINGLE_VECTOR },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
                .driver_data = NVME_QUIRK_SINGLE_VECTOR |
index d20aabc26273c4c2ceda98338efb6e439aebb9e5..3a10e678c7f474f631caf7c195bd7889b6f71516 100644 (file)
@@ -670,7 +670,7 @@ static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
         *   outbound memory @ 3GB). So instead it will  start at the 1x
         *   multiple of its size
         */
-       if (!*rc_bar2_size || *rc_bar2_offset % *rc_bar2_size ||
+       if (!*rc_bar2_size || (*rc_bar2_offset & (*rc_bar2_size - 1)) ||
            (*rc_bar2_offset < SZ_4G && *rc_bar2_offset > SZ_2G)) {
                dev_err(dev, "Invalid rc_bar2_offset/size: size 0x%llx, off 0x%llx\n",
                        *rc_bar2_size, *rc_bar2_offset);
index e69682c95ea2d7f3a0d678b3c7bd3384aa905a7b..62f27610dd33a18cb8e67922489e6811c284eae7 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/platform_data/wilco-ec.h>
 #include <linux/string.h>
-#include <linux/unaligned/le_memmove.h>
+#include <asm/unaligned.h>
 
 /* Operation code; what the EC should do with the property */
 enum ec_property_op {
index da642e811f7f06853ed77defd599afa0eab98a37..4dd2eb6348569965dc4df362e8a6a6f689976f3a 100644 (file)
@@ -303,8 +303,10 @@ static void *
 cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
        struct ccwdev_iter *iter;
+       loff_t p = *offset;
 
-       if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+       (*offset)++;
+       if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
                return NULL;
        iter = it;
        if (iter->devno == __MAX_SUBCHANNEL) {
@@ -314,7 +316,6 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
                        return NULL;
        } else
                iter->devno++;
-       (*offset)++;
        return iter;
 }
 
index 51038ec309c12ef3f3eae351d332ed7a13694eda..dfcbe54591fbda24eb32a4ead5c7c36ec7fd8162 100644 (file)
@@ -135,7 +135,7 @@ static ssize_t chp_measurement_chars_read(struct file *filp,
        struct channel_path *chp;
        struct device *device;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        if (chp->cmg == -1)
                return 0;
@@ -184,7 +184,7 @@ static ssize_t chp_measurement_read(struct file *filp, struct kobject *kobj,
        struct device *device;
        unsigned int size;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        css = to_css(chp->dev.parent);
 
index 3ab8e80d7bbc08f7d9235f2a65d85b8bd012260c..e115623b86b298267e34d09d4da37366421d321c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <asm/qdio.h>
 
 #include "cio.h"
@@ -205,7 +206,7 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
 
        /* fill in sl */
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
-               q->sl->element[j].sbal = (unsigned long)q->sbal[j];
+               q->sl->element[j].sbal = virt_to_phys(q->sbal[j]);
 }
 
 static void setup_queues(struct qdio_irq *irq_ptr,
index d4caf46ff9df155963bf7d01a431212e70fd53d1..2afe2153b34e32e9bc9b25b8a8026d0a0db01be2 100644 (file)
@@ -887,7 +887,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
        /* empty pin tag */
        *p++ = 0x04;
        *p++ = 0;
-       /* encrytped key value tag and bytes */
+       /* encrypted key value tag and bytes */
        p += asn1tag_write(p, 0x04, enckey, enckeysize);
 
        /* reply cprb and payload */
@@ -1095,7 +1095,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
 
        /* Step 1: generate AES 256 bit random kek key */
        rc = ep11_genaeskey(card, domain, 256,
-                           0x00006c00, /* EN/DECRYTP, WRAP/UNWRAP */
+                           0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
                            kek, &keklen);
        if (rc) {
                DEBUG_ERR(
index 9639938581f58e3b0c4151260ce34046b49eeced..8ca85c8a01a15cd000fd1b8b2970ce28207256c3 100644 (file)
@@ -1128,9 +1128,10 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        qeth_tx_complete_buf(buf, error, budget);
 
        for (i = 0; i < queue->max_elements; ++i) {
-               if (buf->buffer->element[i].addr && buf->is_header[i])
-                       kmem_cache_free(qeth_core_header_cache,
-                               buf->buffer->element[i].addr);
+               void *data = phys_to_virt(buf->buffer->element[i].addr);
+
+               if (data && buf->is_header[i])
+                       kmem_cache_free(qeth_core_header_cache, data);
                buf->is_header[i] = 0;
        }
 
@@ -2641,7 +2642,8 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        buf->pool_entry = pool_entry;
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
                buf->buffer->element[i].length = PAGE_SIZE;
-               buf->buffer->element[i].addr =  pool_entry->elements[i];
+               buf->buffer->element[i].addr =
+                       virt_to_phys(pool_entry->elements[i]);
                if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
                        buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY;
                else
@@ -3459,9 +3461,8 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
 
                while ((e < QDIO_MAX_ELEMENTS_PER_BUFFER) &&
                       buffer->element[e].addr) {
-                       unsigned long phys_aob_addr;
+                       unsigned long phys_aob_addr = buffer->element[e].addr;
 
-                       phys_aob_addr = (unsigned long) buffer->element[e].addr;
                        qeth_qdio_handle_aob(card, phys_aob_addr);
                        ++e;
                }
@@ -3750,7 +3751,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                elem_length = min_t(unsigned int, length,
                                    PAGE_SIZE - offset_in_page(data));
 
-               buffer->element[element].addr = data;
+               buffer->element[element].addr = virt_to_phys(data);
                buffer->element[element].length = elem_length;
                length -= elem_length;
                if (is_first_elem) {
@@ -3780,7 +3781,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                        elem_length = min_t(unsigned int, length,
                                            PAGE_SIZE - offset_in_page(data));
 
-                       buffer->element[element].addr = data;
+                       buffer->element[element].addr = virt_to_phys(data);
                        buffer->element[element].length = elem_length;
                        buffer->element[element].eflags =
                                SBAL_EFLAGS_MIDDLE_FRAG;
@@ -3820,7 +3821,7 @@ static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf,
                int element = buf->next_element_to_fill;
                is_first_elem = false;
 
-               buffer->element[element].addr = hdr;
+               buffer->element[element].addr = virt_to_phys(hdr);
                buffer->element[element].length = hd_len;
                buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG;
                /* remember to free cache-allocated qeth_hdr: */
@@ -4746,10 +4747,10 @@ static void qeth_qdio_establish_cq(struct qeth_card *card,
        if (card->options.cq == QETH_CQ_ENABLED) {
                int offset = QDIO_MAX_BUFFERS_PER_Q *
                             (card->qdio.no_in_queues - 1);
-               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-                       in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
-                               virt_to_phys(card->qdio.c_q->bufs[i].buffer);
-               }
+
+               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+                       in_sbal_ptrs[offset + i] =
+                               card->qdio.c_q->bufs[i].buffer;
 
                queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
        }
@@ -4783,10 +4784,9 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_qib_param;
        }
-       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-               in_sbal_ptrs[i] = (struct qdio_buffer *)
-                       virt_to_phys(card->qdio.in_q->bufs[i].buffer);
-       }
+
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+               in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer;
 
        queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *),
                                   GFP_KERNEL);
@@ -4807,11 +4807,11 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_queue_start_poll;
        }
+
        for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
-               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
-                       out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
-                               card->qdio.out_qs[i]->bufs[j]->buffer);
-               }
+               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++)
+                       out_sbal_ptrs[k] =
+                               card->qdio.out_qs[i]->bufs[j]->buffer;
 
        memset(&init_data, 0, sizeof(struct qdio_initialize));
        init_data.cdev                   = CARD_DDEV(card);
@@ -5289,7 +5289,7 @@ next_packet:
                offset = 0;
        }
 
-       hdr = element->addr + offset;
+       hdr = phys_to_virt(element->addr) + offset;
        offset += sizeof(*hdr);
        skb = NULL;
 
@@ -5344,7 +5344,7 @@ next_packet:
        }
 
        use_rx_sg = (card->options.cq == QETH_CQ_ENABLED) ||
-                   ((skb_len >= card->options.rx_sg_cb) &&
+                   (skb_len > card->options.rx_sg_cb &&
                     !atomic_read(&card->force_alloc_skb) &&
                     !IS_OSN(card));
 
@@ -5388,7 +5388,7 @@ use_skb:
 walk_packet:
        while (skb_len) {
                int data_len = min(skb_len, (int)(element->length - offset));
-               char *data = element->addr + offset;
+               char *data = phys_to_virt(element->addr) + offset;
 
                skb_len -= data_len;
                offset += data_len;
@@ -5447,7 +5447,6 @@ static int qeth_extract_skbs(struct qeth_card *card, int budget,
 {
        int work_done = 0;
 
-       WARN_ON_ONCE(!budget);
        *done = false;
 
        while (budget) {
index 692bd26234018f2a260fa16d3085616390a6fab9..9972d96820f3ffbf97513419a19397f75631e8bf 100644 (file)
@@ -1707,15 +1707,14 @@ int qeth_l2_vnicc_set_state(struct qeth_card *card, u32 vnicc, bool state)
 
        QETH_CARD_TEXT(card, 2, "vniccsch");
 
-       /* do not change anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and enable/disable are supported */
        if (!(card->options.vnicc.sup_chars & vnicc) ||
            !(card->options.vnicc.set_char_sup & vnicc))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* set enable/disable command and store wanted characteristic */
        if (state) {
                cmd = IPA_VNICC_ENABLE;
@@ -1761,14 +1760,13 @@ int qeth_l2_vnicc_get_state(struct qeth_card *card, u32 vnicc, bool *state)
 
        QETH_CARD_TEXT(card, 2, "vniccgch");
 
-       /* do not get anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic is supported */
        if (!(card->options.vnicc.sup_chars & vnicc))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* if card is ready, query current VNICC state */
        if (qeth_card_hw_is_reachable(card))
                rc = qeth_l2_vnicc_query_chars(card);
@@ -1786,15 +1784,14 @@ int qeth_l2_vnicc_set_timeout(struct qeth_card *card, u32 timeout)
 
        QETH_CARD_TEXT(card, 2, "vniccsto");
 
-       /* do not change anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and set_timeout are supported */
        if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
            !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* do we need to do anything? */
        if (card->options.vnicc.learning_timeout == timeout)
                return rc;
@@ -1823,14 +1820,14 @@ int qeth_l2_vnicc_get_timeout(struct qeth_card *card, u32 *timeout)
 
        QETH_CARD_TEXT(card, 2, "vniccgto");
 
-       /* do not get anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and get_timeout are supported */
        if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
            !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
                return -EOPNOTSUPP;
+
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* if card is ready, get timeout. Otherwise, just return stored value */
        *timeout = card->options.vnicc.learning_timeout;
        if (qeth_card_hw_is_reachable(card))
index 223a805f0b0bf4bcef3da55d73c86f9705c72463..cae9b7ff79b086e565d63ee8c74122a9dec8a377 100644 (file)
@@ -2510,7 +2510,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
        for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
 
                sbale = &sbal->element[idx];
-               req_id = (unsigned long) sbale->addr;
+               req_id = sbale->addr;
                fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
 
                if (!fsf_req) {
index 2b1e4da1944f572acc88a29726245e9934d00d72..4bfb79f20588b24f00c81e9d094b75a507bb7068 100644 (file)
@@ -410,7 +410,7 @@ struct fsf_qtcb_bottom_port {
        u8 cb_util;
        u8 a_util;
        u8 res2;
-       u16 temperature;
+       s16 temperature;
        u16 vcc;
        u16 tx_bias;
        u16 tx_power;
index 661436a92f8e69903200a568304276b3f3b1b12f..f0d6296e673b46ae27c24ae5dd873f466c58e2b4 100644 (file)
@@ -98,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
                        memset(pl, 0,
                               ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
                        sbale = qdio->res_q[idx]->element;
-                       req_id = (u64) sbale->addr;
+                       req_id = sbale->addr;
                        scount = min(sbale->scount + 1,
                                     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
                                     /* incl. signaling SBAL */
@@ -199,7 +199,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                             q_req->sbal_number);
                        return -EINVAL;
                }
-               sbale->addr = sg_virt(sg);
+               sbale->addr = sg_phys(sg);
                sbale->length = sg->length;
        }
        return 0;
@@ -418,7 +418,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
                sbale->length = 0;
                sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
                sbale->sflags = 0;
-               sbale->addr = NULL;
+               sbale->addr = 0;
        }
 
        if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
index 2a816a37b3c018399157926ef8ffbcfe94d52a7a..6b43d6b254bef2e34757a4bafe92bc3d0a19129a 100644 (file)
@@ -122,14 +122,14 @@ void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                        % QDIO_MAX_BUFFERS_PER_Q;
 
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->addr = (void *) req_id;
+       sbale->addr = req_id;
        sbale->eflags = 0;
        sbale->sflags = SBAL_SFLAGS0_COMMAND | sbtype;
 
        if (unlikely(!data))
                return;
        sbale++;
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
@@ -152,7 +152,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
        BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
        q_req->sbale_curr++;
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
index 494b9fe9cc944c55011f16ccf04bea12d92f40a9..a711a0d151002d7b16212d15130a1362b1ff7a13 100644 (file)
@@ -800,7 +800,7 @@ static ZFCP_DEV_ATTR(adapter_diag, b2b_credit, 0400,
        static ZFCP_DEV_ATTR(adapter_diag_sfp, _name, 0400,                    \
                             zfcp_sysfs_adapter_diag_sfp_##_name##_show, NULL)
 
-ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 6, "%hd");
 ZFCP_DEFINE_DIAG_SFP_ATTR(vcc, vcc, 5, "%hu");
 ZFCP_DEFINE_DIAG_SFP_ATTR(tx_bias, tx_bias, 5, "%hu");
 ZFCP_DEFINE_DIAG_SFP_ATTR(tx_power, tx_power, 5, "%hu");
index 9c5f7c9178c66351a5c74e0b1e8c12c359ae8776..2b865c6423e293b6e3b4a04cac83a5a4923d0e72 100644 (file)
@@ -628,6 +628,8 @@ redisc:
        }
 out:
        kref_put(&rdata->kref, fc_rport_destroy);
+       if (!IS_ERR(fp))
+               fc_frame_free(fp);
 }
 
 /**
index f3b36fd0a0ebd6f5d09690f12b20f4360d12ea47..b2ad96564484000ca4ca1c10bb9f984601a8ace9 100644 (file)
@@ -623,7 +623,8 @@ retry_alloc:
 
        fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                               GFP_KERNEL, &fusion->io_request_frames_phys);
+                               GFP_KERNEL | __GFP_NOWARN,
+                               &fusion->io_request_frames_phys);
        if (!fusion->io_request_frames) {
                if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) {
                        instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT;
@@ -661,7 +662,7 @@ retry_alloc:
 
                fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                                      GFP_KERNEL,
+                                      GFP_KERNEL | __GFP_NOWARN,
                                       &fusion->io_request_frames_phys);
 
                if (!fusion->io_request_frames) {
index e4282bce583475a046a679093d4ddf6cc706b105..f45c22b097269b555255731065d301f6a47b7315 100644 (file)
@@ -161,6 +161,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                        unsigned int nr_zones, report_zones_cb cb, void *data)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
+       sector_t capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
        unsigned int nr, i;
        unsigned char *buf;
        size_t offset, buflen = 0;
@@ -171,11 +172,15 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                /* Not a zoned device */
                return -EOPNOTSUPP;
 
+       if (!capacity)
+               /* Device gone or invalid */
+               return -ENODEV;
+
        buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen);
        if (!buf)
                return -ENOMEM;
 
-       while (zone_idx < nr_zones && sector < get_capacity(disk)) {
+       while (zone_idx < nr_zones && sector < capacity) {
                ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
                                sectors_to_logical(sdkp->device, sector), true);
                if (ret)
index 0fbb8fe6e521b9edf427435b4d6ef2a41008054b..e4240e4ae8bbdcae4f850778deae56968c937c05 100644 (file)
@@ -688,7 +688,7 @@ static const struct block_device_operations sr_bdops =
        .release        = sr_block_release,
        .ioctl          = sr_block_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl          = sr_block_compat_ioctl,
+       .compat_ioctl   = sr_block_compat_ioctl,
 #endif
        .check_events   = sr_block_check_events,
        .revalidate_disk = sr_block_revalidate_disk,
index d6d605d5cbde919b372b533910813051b7f91e35..8d8fd5c29349a836cd3444dac91c2ffa02e10dec 100644 (file)
@@ -14,14 +14,6 @@ config ASHMEM
          It is, in theory, a good memory allocator for low-memory devices,
          because it can discard shared memory units when under memory pressure.
 
-config ANDROID_VSOC
-       tristate "Android Virtual SoC support"
-       depends on PCI_MSI
-       help
-         This option adds support for the Virtual SoC driver needed to boot
-         a 'cuttlefish' Android image inside QEmu. The driver interacts with
-         a QEmu ivshmem device. If built as a module, it will be called vsoc.
-
 source "drivers/staging/android/ion/Kconfig"
 
 endif # if ANDROID
index 14bd9c6ce10d3868051306e64213bf57d9dffaac..3b66cd0b0ec56d3a9d1da56b280333d3a4cdb078 100644 (file)
@@ -4,4 +4,3 @@ ccflags-y += -I$(src)                   # needed for trace events
 obj-y                                  += ion/
 
 obj-$(CONFIG_ASHMEM)                   += ashmem.o
-obj-$(CONFIG_ANDROID_VSOC)             += vsoc.o
index 767dd98fd92d55f91398c9e5a824782034634650..80eccfaf6db53c40f8beadee75e5f778e7532d44 100644 (file)
@@ -9,14 +9,5 @@ ion/
  - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0)
  - Better test framework (integration with VGEM was suggested)
 
-vsoc.c, uapi/vsoc_shm.h
- - The current driver uses the same wait queue for all of the futexes in a
-   region. This will cause false wakeups in regions with a large number of
-   waiting threads. We should eventually use multiple queues and select the
-   queue based on the region.
- - Add debugfs support for examining the permissions of regions.
- - Remove VSOC_WAIT_FOR_INCOMING_INTERRUPT ioctl. This functionality has been
-   superseded by the futex and is there for legacy reasons.
-
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
 Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com>
index 5891d0744a760b2fb8e690ac6fea2e91d96927a3..8044510d8ec673667a7ba9c90426e961a28e89c3 100644 (file)
@@ -351,8 +351,23 @@ static inline vm_flags_t calc_vm_may_flags(unsigned long prot)
               _calc_vm_trans(prot, PROT_EXEC,  VM_MAYEXEC);
 }
 
+static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       /* do not allow to mmap ashmem backing shmem file directly */
+       return -EPERM;
+}
+
+static unsigned long
+ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
+                               unsigned long len, unsigned long pgoff,
+                               unsigned long flags)
+{
+       return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+}
+
 static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       static struct file_operations vmfile_fops;
        struct ashmem_area *asma = file->private_data;
        int ret = 0;
 
@@ -393,6 +408,19 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
                }
                vmfile->f_mode |= FMODE_LSEEK;
                asma->file = vmfile;
+               /*
+                * override mmap operation of the vmfile so that it can't be
+                * remapped which would lead to creation of a new vma with no
+                * asma permission checks. Have to override get_unmapped_area
+                * as well to prevent VM_BUG_ON check for f_ops modification.
+                */
+               if (!vmfile_fops.mmap) {
+                       vmfile_fops = *vmfile->f_op;
+                       vmfile_fops.mmap = ashmem_vmfile_mmap;
+                       vmfile_fops.get_unmapped_area =
+                                       ashmem_vmfile_get_unmapped_area;
+               }
+               vmfile->f_op = &vmfile_fops;
        }
        get_file(asma->file);
 
diff --git a/drivers/staging/android/uapi/vsoc_shm.h b/drivers/staging/android/uapi/vsoc_shm.h
deleted file mode 100644 (file)
index 6291fb2..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2017 Google, Inc.
- *
- */
-
-#ifndef _UAPI_LINUX_VSOC_SHM_H
-#define _UAPI_LINUX_VSOC_SHM_H
-
-#include <linux/types.h>
-
-/**
- * A permission is a token that permits a receiver to read and/or write an area
- * of memory within a Vsoc region.
- *
- * An fd_scoped permission grants both read and write access, and can be
- * attached to a file description (see open(2)).
- * Ownership of the area can then be shared by passing a file descriptor
- * among processes.
- *
- * begin_offset and end_offset define the area of memory that is controlled by
- * the permission. owner_offset points to a word, also in shared memory, that
- * controls ownership of the area.
- *
- * ownership of the region expires when the associated file description is
- * released.
- *
- * At most one permission can be attached to each file description.
- *
- * This is useful when implementing HALs like gralloc that scope and pass
- * ownership of shared resources via file descriptors.
- *
- * The caller is responsibe for doing any fencing.
- *
- * The calling process will normally identify a currently free area of
- * memory. It will construct a proposed fd_scoped_permission_arg structure:
- *
- *   begin_offset and end_offset describe the area being claimed
- *
- *   owner_offset points to the location in shared memory that indicates the
- *   owner of the area.
- *
- *   owned_value is the value that will be stored in owner_offset iff the
- *   permission can be granted. It must be different than VSOC_REGION_FREE.
- *
- * Two fd_scoped_permission structures are compatible if they vary only by
- * their owned_value fields.
- *
- * The driver ensures that, for any group of simultaneous callers proposing
- * compatible fd_scoped_permissions, it will accept exactly one of the
- * propopsals. The other callers will get a failure with errno of EAGAIN.
- *
- * A process receiving a file descriptor can identify the region being
- * granted using the VSOC_GET_FD_SCOPED_PERMISSION ioctl.
- */
-struct fd_scoped_permission {
-       __u32 begin_offset;
-       __u32 end_offset;
-       __u32 owner_offset;
-       __u32 owned_value;
-};
-
-/*
- * This value represents a free area of memory. The driver expects to see this
- * value at owner_offset when creating a permission otherwise it will not do it,
- * and will write this value back once the permission is no longer needed.
- */
-#define VSOC_REGION_FREE ((__u32)0)
-
-/**
- * ioctl argument for VSOC_CREATE_FD_SCOPE_PERMISSION
- */
-struct fd_scoped_permission_arg {
-       struct fd_scoped_permission perm;
-       __s32 managed_region_fd;
-};
-
-#define VSOC_NODE_FREE ((__u32)0)
-
-/*
- * Describes a signal table in shared memory. Each non-zero entry in the
- * table indicates that the receiver should signal the futex at the given
- * offset. Offsets are relative to the region, not the shared memory window.
- *
- * interrupt_signalled_offset is used to reliably signal interrupts across the
- * vmm boundary. There are two roles: transmitter and receiver. For example,
- * in the host_to_guest_signal_table the host is the transmitter and the
- * guest is the receiver. The protocol is as follows:
- *
- * 1. The transmitter should convert the offset of the futex to an offset
- *    in the signal table [0, (1 << num_nodes_lg2))
- *    The transmitter can choose any appropriate hashing algorithm, including
- *    hash = futex_offset & ((1 << num_nodes_lg2) - 1)
- *
- * 3. The transmitter should atomically compare and swap futex_offset with 0
- *    at hash. There are 3 possible outcomes
- *      a. The swap fails because the futex_offset is already in the table.
- *         The transmitter should stop.
- *      b. Some other offset is in the table. This is a hash collision. The
- *         transmitter should move to another table slot and try again. One
- *         possible algorithm:
- *         hash = (hash + 1) & ((1 << num_nodes_lg2) - 1)
- *      c. The swap worked. Continue below.
- *
- * 3. The transmitter atomically swaps 1 with the value at the
- *    interrupt_signalled_offset. There are two outcomes:
- *      a. The prior value was 1. In this case an interrupt has already been
- *         posted. The transmitter is done.
- *      b. The prior value was 0, indicating that the receiver may be sleeping.
- *         The transmitter will issue an interrupt.
- *
- * 4. On waking the receiver immediately exchanges a 0 with the
- *    interrupt_signalled_offset. If it receives a 0 then this a spurious
- *    interrupt. That may occasionally happen in the current protocol, but
- *    should be rare.
- *
- * 5. The receiver scans the signal table by atomicaly exchanging 0 at each
- *    location. If a non-zero offset is returned from the exchange the
- *    receiver wakes all sleepers at the given offset:
- *      futex((int*)(region_base + old_value), FUTEX_WAKE, MAX_INT);
- *
- * 6. The receiver thread then does a conditional wait, waking immediately
- *    if the value at interrupt_signalled_offset is non-zero. This catches cases
- *    here additional  signals were posted while the table was being scanned.
- *    On the guest the wait is handled via the VSOC_WAIT_FOR_INCOMING_INTERRUPT
- *    ioctl.
- */
-struct vsoc_signal_table_layout {
-       /* log_2(Number of signal table entries) */
-       __u32 num_nodes_lg2;
-       /*
-        * Offset to the first signal table entry relative to the start of the
-        * region
-        */
-       __u32 futex_uaddr_table_offset;
-       /*
-        * Offset to an atomic_t / atomic uint32_t. A non-zero value indicates
-        * that one or more offsets are currently posted in the table.
-        * semi-unique access to an entry in the table
-        */
-       __u32 interrupt_signalled_offset;
-};
-
-#define VSOC_REGION_WHOLE ((__s32)0)
-#define VSOC_DEVICE_NAME_SZ 16
-
-/**
- * Each HAL would (usually) talk to a single device region
- * Mulitple entities care about these regions:
- * - The ivshmem_server will populate the regions in shared memory
- * - The guest kernel will read the region, create minor device nodes, and
- *   allow interested parties to register for FUTEX_WAKE events in the region
- * - HALs will access via the minor device nodes published by the guest kernel
- * - Host side processes will access the region via the ivshmem_server:
- *   1. Pass name to ivshmem_server at a UNIX socket
- *   2. ivshmemserver will reply with 2 fds:
- *     - host->guest doorbell fd
- *     - guest->host doorbell fd
- *     - fd for the shared memory region
- *     - region offset
- *   3. Start a futex receiver thread on the doorbell fd pointed at the
- *      signal_nodes
- */
-struct vsoc_device_region {
-       __u16 current_version;
-       __u16 min_compatible_version;
-       __u32 region_begin_offset;
-       __u32 region_end_offset;
-       __u32 offset_of_region_data;
-       struct vsoc_signal_table_layout guest_to_host_signal_table;
-       struct vsoc_signal_table_layout host_to_guest_signal_table;
-       /* Name of the device. Must always be terminated with a '\0', so
-        * the longest supported device name is 15 characters.
-        */
-       char device_name[VSOC_DEVICE_NAME_SZ];
-       /* There are two ways that permissions to access regions are handled:
-        *   - When subdivided_by is VSOC_REGION_WHOLE, any process that can
-        *     open the device node for the region gains complete access to it.
-        *   - When subdivided is set processes that open the region cannot
-        *     access it. Access to a sub-region must be established by invoking
-        *     the VSOC_CREATE_FD_SCOPE_PERMISSION ioctl on the region
-        *     referenced in subdivided_by, providing a fileinstance
-        *     (represented by a fd) opened on this region.
-        */
-       __u32 managed_by;
-};
-
-/*
- * The vsoc layout descriptor.
- * The first 4K should be reserved for the shm header and region descriptors.
- * The regions should be page aligned.
- */
-
-struct vsoc_shm_layout_descriptor {
-       __u16 major_version;
-       __u16 minor_version;
-
-       /* size of the shm. This may be redundant but nice to have */
-       __u32 size;
-
-       /* number of shared memory regions */
-       __u32 region_count;
-
-       /* The offset to the start of region descriptors */
-       __u32 vsoc_region_desc_offset;
-};
-
-/*
- * This specifies the current version that should be stored in
- * vsoc_shm_layout_descriptor.major_version and
- * vsoc_shm_layout_descriptor.minor_version.
- * It should be updated only if the vsoc_device_region and
- * vsoc_shm_layout_descriptor structures have changed.
- * Versioning within each region is transferred
- * via the min_compatible_version and current_version fields in
- * vsoc_device_region. The driver does not consult these fields: they are left
- * for the HALs and host processes and will change independently of the layout
- * version.
- */
-#define CURRENT_VSOC_LAYOUT_MAJOR_VERSION 2
-#define CURRENT_VSOC_LAYOUT_MINOR_VERSION 0
-
-#define VSOC_CREATE_FD_SCOPED_PERMISSION \
-       _IOW(0xF5, 0, struct fd_scoped_permission)
-#define VSOC_GET_FD_SCOPED_PERMISSION _IOR(0xF5, 1, struct fd_scoped_permission)
-
-/*
- * This is used to signal the host to scan the guest_to_host_signal_table
- * for new futexes to wake. This sends an interrupt if one is not already
- * in flight.
- */
-#define VSOC_MAYBE_SEND_INTERRUPT_TO_HOST _IO(0xF5, 2)
-
-/*
- * When this returns the guest will scan host_to_guest_signal_table to
- * check for new futexes to wake.
- */
-/* TODO(ghartman): Consider moving this to the bottom half */
-#define VSOC_WAIT_FOR_INCOMING_INTERRUPT _IO(0xF5, 3)
-
-/*
- * Guest HALs will use this to retrieve the region description after
- * opening their device node.
- */
-#define VSOC_DESCRIBE_REGION _IOR(0xF5, 4, struct vsoc_device_region)
-
-/*
- * Wake any threads that may be waiting for a host interrupt on this region.
- * This is mostly used during shutdown.
- */
-#define VSOC_SELF_INTERRUPT _IO(0xF5, 5)
-
-/*
- * This is used to signal the host to scan the guest_to_host_signal_table
- * for new futexes to wake. This sends an interrupt unconditionally.
- */
-#define VSOC_SEND_INTERRUPT_TO_HOST _IO(0xF5, 6)
-
-enum wait_types {
-       VSOC_WAIT_UNDEFINED = 0,
-       VSOC_WAIT_IF_EQUAL = 1,
-       VSOC_WAIT_IF_EQUAL_TIMEOUT = 2
-};
-
-/*
- * Wait for a condition to be true
- *
- * Note, this is sized and aligned so the 32 bit and 64 bit layouts are
- * identical.
- */
-struct vsoc_cond_wait {
-       /* Input: Offset of the 32 bit word to check */
-       __u32 offset;
-       /* Input: Value that will be compared with the offset */
-       __u32 value;
-       /* Monotonic time to wake at in seconds */
-       __u64 wake_time_sec;
-       /* Input: Monotonic time to wait in nanoseconds */
-       __u32 wake_time_nsec;
-       /* Input: Type of wait */
-       __u32 wait_type;
-       /* Output: Number of times the thread woke before returning. */
-       __u32 wakes;
-       /* Ensure that we're 8-byte aligned and 8 byte length for 32/64 bit
-        * compatibility.
-        */
-       __u32 reserved_1;
-};
-
-#define VSOC_COND_WAIT _IOWR(0xF5, 7, struct vsoc_cond_wait)
-
-/* Wake any local threads waiting at the offset given in arg */
-#define VSOC_COND_WAKE _IO(0xF5, 8)
-
-#endif /* _UAPI_LINUX_VSOC_SHM_H */
diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c
deleted file mode 100644 (file)
index 1240bb0..0000000
+++ /dev/null
@@ -1,1149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * drivers/android/staging/vsoc.c
- *
- * Android Virtual System on a Chip (VSoC) driver
- *
- * Copyright (C) 2017 Google, Inc.
- *
- * Author: ghartman@google.com
- *
- * Based on drivers/char/kvm_ivshmem.c - driver for KVM Inter-VM shared memory
- *         Copyright 2009 Cam Macdonell <cam@cs.ualberta.ca>
- *
- * Based on cirrusfb.c and 8139cp.c:
- *   Copyright 1999-2001 Jeff Garzik
- *   Copyright 2001-2004 Jeff Garzik
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/freezer.h>
-#include <linux/futex.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <linux/syscalls.h>
-#include <linux/uaccess.h>
-#include <linux/interrupt.h>
-#include <linux/cdev.h>
-#include <linux/file.h>
-#include "uapi/vsoc_shm.h"
-
-#define VSOC_DEV_NAME "vsoc"
-
-/*
- * Description of the ivshmem-doorbell PCI device used by QEmu. These
- * constants follow docs/specs/ivshmem-spec.txt, which can be found in
- * the QEmu repository. This was last reconciled with the version that
- * came out with 2.8
- */
-
-/*
- * These constants are determined KVM Inter-VM shared memory device
- * register offsets
- */
-enum {
-       INTR_MASK = 0x00,       /* Interrupt Mask */
-       INTR_STATUS = 0x04,     /* Interrupt Status */
-       IV_POSITION = 0x08,     /* VM ID */
-       DOORBELL = 0x0c,        /* Doorbell */
-};
-
-static const int REGISTER_BAR;  /* Equal to 0 */
-static const int MAX_REGISTER_BAR_LEN = 0x100;
-/*
- * The MSI-x BAR is not used directly.
- *
- * static const int MSI_X_BAR = 1;
- */
-static const int SHARED_MEMORY_BAR = 2;
-
-struct vsoc_region_data {
-       char name[VSOC_DEVICE_NAME_SZ + 1];
-       wait_queue_head_t interrupt_wait_queue;
-       /* TODO(b/73664181): Use multiple futex wait queues */
-       wait_queue_head_t futex_wait_queue;
-       /* Flag indicating that an interrupt has been signalled by the host. */
-       atomic_t *incoming_signalled;
-       /* Flag indicating the guest has signalled the host. */
-       atomic_t *outgoing_signalled;
-       bool irq_requested;
-       bool device_created;
-};
-
-struct vsoc_device {
-       /* Kernel virtual address of REGISTER_BAR. */
-       void __iomem *regs;
-       /* Physical address of SHARED_MEMORY_BAR. */
-       phys_addr_t shm_phys_start;
-       /* Kernel virtual address of SHARED_MEMORY_BAR. */
-       void __iomem *kernel_mapped_shm;
-       /* Size of the entire shared memory window in bytes. */
-       size_t shm_size;
-       /*
-        * Pointer to the virtual address of the shared memory layout structure.
-        * This is probably identical to kernel_mapped_shm, but saving this
-        * here saves a lot of annoying casts.
-        */
-       struct vsoc_shm_layout_descriptor *layout;
-       /*
-        * Points to a table of region descriptors in the kernel's virtual
-        * address space. Calculated from
-        * vsoc_shm_layout_descriptor.vsoc_region_desc_offset
-        */
-       struct vsoc_device_region *regions;
-       /* Head of a list of permissions that have been granted. */
-       struct list_head permissions;
-       struct pci_dev *dev;
-       /* Per-region (and therefore per-interrupt) information. */
-       struct vsoc_region_data *regions_data;
-       /*
-        * Table of msi-x entries. This has to be separated from struct
-        * vsoc_region_data because the kernel deals with them as an array.
-        */
-       struct msix_entry *msix_entries;
-       /* Mutex that protectes the permission list */
-       struct mutex mtx;
-       /* Major number assigned by the kernel */
-       int major;
-       /* Character device assigned by the kernel */
-       struct cdev cdev;
-       /* Device class assigned by the kernel */
-       struct class *class;
-       /*
-        * Flags that indicate what we've initialized. These are used to do an
-        * orderly cleanup of the device.
-        */
-       bool enabled_device;
-       bool requested_regions;
-       bool cdev_added;
-       bool class_added;
-       bool msix_enabled;
-};
-
-static struct vsoc_device vsoc_dev;
-
-/*
- * TODO(ghartman): Add a /sys filesystem entry that summarizes the permissions.
- */
-
-struct fd_scoped_permission_node {
-       struct fd_scoped_permission permission;
-       struct list_head list;
-};
-
-struct vsoc_private_data {
-       struct fd_scoped_permission_node *fd_scoped_permission_node;
-};
-
-static long vsoc_ioctl(struct file *, unsigned int, unsigned long);
-static int vsoc_mmap(struct file *, struct vm_area_struct *);
-static int vsoc_open(struct inode *, struct file *);
-static int vsoc_release(struct inode *, struct file *);
-static ssize_t vsoc_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t vsoc_write(struct file *, const char __user *, size_t, loff_t *);
-static loff_t vsoc_lseek(struct file *filp, loff_t offset, int origin);
-static int
-do_create_fd_scoped_permission(struct vsoc_device_region *region_p,
-                              struct fd_scoped_permission_node *np,
-                              struct fd_scoped_permission_arg __user *arg);
-static void
-do_destroy_fd_scoped_permission(struct vsoc_device_region *owner_region_p,
-                               struct fd_scoped_permission *perm);
-static long do_vsoc_describe_region(struct file *,
-                                   struct vsoc_device_region __user *);
-static ssize_t vsoc_get_area(struct file *filp, __u32 *perm_off);
-
-/**
- * Validate arguments on entry points to the driver.
- */
-inline int vsoc_validate_inode(struct inode *inode)
-{
-       if (iminor(inode) >= vsoc_dev.layout->region_count) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "describe_region: invalid region %d\n", iminor(inode));
-               return -ENODEV;
-       }
-       return 0;
-}
-
-inline int vsoc_validate_filep(struct file *filp)
-{
-       int ret = vsoc_validate_inode(file_inode(filp));
-
-       if (ret)
-               return ret;
-       if (!filp->private_data) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "No private data on fd, region %d\n",
-                       iminor(file_inode(filp)));
-               return -EBADFD;
-       }
-       return 0;
-}
-
-/* Converts from shared memory offset to virtual address */
-static inline void *shm_off_to_virtual_addr(__u32 offset)
-{
-       return (void __force *)vsoc_dev.kernel_mapped_shm + offset;
-}
-
-/* Converts from shared memory offset to physical address */
-static inline phys_addr_t shm_off_to_phys_addr(__u32 offset)
-{
-       return vsoc_dev.shm_phys_start + offset;
-}
-
-/**
- * Convenience functions to obtain the region from the inode or file.
- * Dangerous to call before validating the inode/file.
- */
-static
-inline struct vsoc_device_region *vsoc_region_from_inode(struct inode *inode)
-{
-       return &vsoc_dev.regions[iminor(inode)];
-}
-
-static
-inline struct vsoc_device_region *vsoc_region_from_filep(struct file *inode)
-{
-       return vsoc_region_from_inode(file_inode(inode));
-}
-
-static inline uint32_t vsoc_device_region_size(struct vsoc_device_region *r)
-{
-       return r->region_end_offset - r->region_begin_offset;
-}
-
-static const struct file_operations vsoc_ops = {
-       .owner = THIS_MODULE,
-       .open = vsoc_open,
-       .mmap = vsoc_mmap,
-       .read = vsoc_read,
-       .unlocked_ioctl = vsoc_ioctl,
-       .compat_ioctl = vsoc_ioctl,
-       .write = vsoc_write,
-       .llseek = vsoc_lseek,
-       .release = vsoc_release,
-};
-
-static struct pci_device_id vsoc_id_table[] = {
-       {0x1af4, 0x1110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0},
-};
-
-MODULE_DEVICE_TABLE(pci, vsoc_id_table);
-
-static void vsoc_remove_device(struct pci_dev *pdev);
-static int vsoc_probe_device(struct pci_dev *pdev,
-                            const struct pci_device_id *ent);
-
-static struct pci_driver vsoc_pci_driver = {
-       .name = "vsoc",
-       .id_table = vsoc_id_table,
-       .probe = vsoc_probe_device,
-       .remove = vsoc_remove_device,
-};
-
-static int
-do_create_fd_scoped_permission(struct vsoc_device_region *region_p,
-                              struct fd_scoped_permission_node *np,
-                              struct fd_scoped_permission_arg __user *arg)
-{
-       struct file *managed_filp;
-       s32 managed_fd;
-       atomic_t *owner_ptr = NULL;
-       struct vsoc_device_region *managed_region_p;
-
-       if (copy_from_user(&np->permission,
-                          &arg->perm, sizeof(np->permission)) ||
-           copy_from_user(&managed_fd,
-                          &arg->managed_region_fd, sizeof(managed_fd))) {
-               return -EFAULT;
-       }
-       managed_filp = fdget(managed_fd).file;
-       /* Check that it's a valid fd, */
-       if (!managed_filp || vsoc_validate_filep(managed_filp))
-               return -EPERM;
-       /* EEXIST if the given fd already has a permission. */
-       if (((struct vsoc_private_data *)managed_filp->private_data)->
-           fd_scoped_permission_node)
-               return -EEXIST;
-       managed_region_p = vsoc_region_from_filep(managed_filp);
-       /* Check that the provided region is managed by this one */
-       if (&vsoc_dev.regions[managed_region_p->managed_by] != region_p)
-               return -EPERM;
-       /* The area must be well formed and have non-zero size */
-       if (np->permission.begin_offset >= np->permission.end_offset)
-               return -EINVAL;
-       /* The area must fit in the memory window */
-       if (np->permission.end_offset >
-           vsoc_device_region_size(managed_region_p))
-               return -ERANGE;
-       /* The area must be in the region data section */
-       if (np->permission.begin_offset <
-           managed_region_p->offset_of_region_data)
-               return -ERANGE;
-       /* The area must be page aligned */
-       if (!PAGE_ALIGNED(np->permission.begin_offset) ||
-           !PAGE_ALIGNED(np->permission.end_offset))
-               return -EINVAL;
-       /* Owner offset must be naturally aligned in the window */
-       if (np->permission.owner_offset &
-           (sizeof(np->permission.owner_offset) - 1))
-               return -EINVAL;
-       /* The owner flag must reside in the owner memory */
-       if (np->permission.owner_offset + sizeof(np->permission.owner_offset) >
-           vsoc_device_region_size(region_p))
-               return -ERANGE;
-       /* The owner flag must reside in the data section */
-       if (np->permission.owner_offset < region_p->offset_of_region_data)
-               return -EINVAL;
-       /* The owner value must change to claim the memory */
-       if (np->permission.owned_value == VSOC_REGION_FREE)
-               return -EINVAL;
-       owner_ptr =
-           (atomic_t *)shm_off_to_virtual_addr(region_p->region_begin_offset +
-                                               np->permission.owner_offset);
-       /* We've already verified that this is in the shared memory window, so
-        * it should be safe to write to this address.
-        */
-       if (atomic_cmpxchg(owner_ptr,
-                          VSOC_REGION_FREE,
-                          np->permission.owned_value) != VSOC_REGION_FREE) {
-               return -EBUSY;
-       }
-       ((struct vsoc_private_data *)managed_filp->private_data)->
-           fd_scoped_permission_node = np;
-       /* The file offset needs to be adjusted if the calling
-        * process did any read/write operations on the fd
-        * before creating the permission.
-        */
-       if (managed_filp->f_pos) {
-               if (managed_filp->f_pos > np->permission.end_offset) {
-                       /* If the offset is beyond the permission end, set it
-                        * to the end.
-                        */
-                       managed_filp->f_pos = np->permission.end_offset;
-               } else {
-                       /* If the offset is within the permission interval
-                        * keep it there otherwise reset it to zero.
-                        */
-                       if (managed_filp->f_pos < np->permission.begin_offset) {
-                               managed_filp->f_pos = 0;
-                       } else {
-                               managed_filp->f_pos -=
-                                   np->permission.begin_offset;
-                       }
-               }
-       }
-       return 0;
-}
-
-static void
-do_destroy_fd_scoped_permission_node(struct vsoc_device_region *owner_region_p,
-                                    struct fd_scoped_permission_node *node)
-{
-       if (node) {
-               do_destroy_fd_scoped_permission(owner_region_p,
-                                               &node->permission);
-               mutex_lock(&vsoc_dev.mtx);
-               list_del(&node->list);
-               mutex_unlock(&vsoc_dev.mtx);
-               kfree(node);
-       }
-}
-
-static void
-do_destroy_fd_scoped_permission(struct vsoc_device_region *owner_region_p,
-                               struct fd_scoped_permission *perm)
-{
-       atomic_t *owner_ptr = NULL;
-       int prev = 0;
-
-       if (!perm)
-               return;
-       owner_ptr = (atomic_t *)shm_off_to_virtual_addr
-               (owner_region_p->region_begin_offset + perm->owner_offset);
-       prev = atomic_xchg(owner_ptr, VSOC_REGION_FREE);
-       if (prev != perm->owned_value)
-               dev_err(&vsoc_dev.dev->dev,
-                       "%x-%x: owner (%s) %x: expected to be %x was %x",
-                       perm->begin_offset, perm->end_offset,
-                       owner_region_p->device_name, perm->owner_offset,
-                       perm->owned_value, prev);
-}
-
-static long do_vsoc_describe_region(struct file *filp,
-                                   struct vsoc_device_region __user *dest)
-{
-       struct vsoc_device_region *region_p;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       region_p = vsoc_region_from_filep(filp);
-       if (copy_to_user(dest, region_p, sizeof(*region_p)))
-               return -EFAULT;
-       return 0;
-}
-
-/**
- * Implements the inner logic of cond_wait. Copies to and from userspace are
- * done in the helper function below.
- */
-static int handle_vsoc_cond_wait(struct file *filp, struct vsoc_cond_wait *arg)
-{
-       DEFINE_WAIT(wait);
-       u32 region_number = iminor(file_inode(filp));
-       struct vsoc_region_data *data = vsoc_dev.regions_data + region_number;
-       struct hrtimer_sleeper timeout, *to = NULL;
-       int ret = 0;
-       struct vsoc_device_region *region_p = vsoc_region_from_filep(filp);
-       atomic_t *address = NULL;
-       ktime_t wake_time;
-
-       /* Ensure that the offset is aligned */
-       if (arg->offset & (sizeof(uint32_t) - 1))
-               return -EADDRNOTAVAIL;
-       /* Ensure that the offset is within shared memory */
-       if (((uint64_t)arg->offset) + region_p->region_begin_offset +
-           sizeof(uint32_t) > region_p->region_end_offset)
-               return -E2BIG;
-       address = shm_off_to_virtual_addr(region_p->region_begin_offset +
-                                         arg->offset);
-
-       /* Ensure that the type of wait is valid */
-       switch (arg->wait_type) {
-       case VSOC_WAIT_IF_EQUAL:
-               break;
-       case VSOC_WAIT_IF_EQUAL_TIMEOUT:
-               to = &timeout;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (to) {
-               /* Copy the user-supplied timesec into the kernel structure.
-                * We do things this way to flatten differences between 32 bit
-                * and 64 bit timespecs.
-                */
-               if (arg->wake_time_nsec >= NSEC_PER_SEC)
-                       return -EINVAL;
-               wake_time = ktime_set(arg->wake_time_sec, arg->wake_time_nsec);
-
-               hrtimer_init_sleeper_on_stack(to, CLOCK_MONOTONIC,
-                                             HRTIMER_MODE_ABS);
-               hrtimer_set_expires_range_ns(&to->timer, wake_time,
-                                            current->timer_slack_ns);
-       }
-
-       while (1) {
-               prepare_to_wait(&data->futex_wait_queue, &wait,
-                               TASK_INTERRUPTIBLE);
-               /*
-                * Check the sentinel value after prepare_to_wait. If the value
-                * changes after this check the writer will call signal,
-                * changing the task state from INTERRUPTIBLE to RUNNING. That
-                * will ensure that schedule() will eventually schedule this
-                * task.
-                */
-               if (atomic_read(address) != arg->value) {
-                       ret = 0;
-                       break;
-               }
-               if (to) {
-                       hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
-                       if (likely(to->task))
-                               freezable_schedule();
-                       hrtimer_cancel(&to->timer);
-                       if (!to->task) {
-                               ret = -ETIMEDOUT;
-                               break;
-                       }
-               } else {
-                       freezable_schedule();
-               }
-               /* Count the number of times that we woke up. This is useful
-                * for unit testing.
-                */
-               ++arg->wakes;
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       break;
-               }
-       }
-       finish_wait(&data->futex_wait_queue, &wait);
-       if (to)
-               destroy_hrtimer_on_stack(&to->timer);
-       return ret;
-}
-
-/**
- * Handles the details of copying from/to userspace to ensure that the copies
- * happen on all of the return paths of cond_wait.
- */
-static int do_vsoc_cond_wait(struct file *filp,
-                            struct vsoc_cond_wait __user *untrusted_in)
-{
-       struct vsoc_cond_wait arg;
-       int rval = 0;
-
-       if (copy_from_user(&arg, untrusted_in, sizeof(arg)))
-               return -EFAULT;
-       /* wakes is an out parameter. Initialize it to something sensible. */
-       arg.wakes = 0;
-       rval = handle_vsoc_cond_wait(filp, &arg);
-       if (copy_to_user(untrusted_in, &arg, sizeof(arg)))
-               return -EFAULT;
-       return rval;
-}
-
-static int do_vsoc_cond_wake(struct file *filp, uint32_t offset)
-{
-       struct vsoc_device_region *region_p = vsoc_region_from_filep(filp);
-       u32 region_number = iminor(file_inode(filp));
-       struct vsoc_region_data *data = vsoc_dev.regions_data + region_number;
-       /* Ensure that the offset is aligned */
-       if (offset & (sizeof(uint32_t) - 1))
-               return -EADDRNOTAVAIL;
-       /* Ensure that the offset is within shared memory */
-       if (((uint64_t)offset) + region_p->region_begin_offset +
-           sizeof(uint32_t) > region_p->region_end_offset)
-               return -E2BIG;
-       /*
-        * TODO(b/73664181): Use multiple futex wait queues.
-        * We need to wake every sleeper when the condition changes. Typically
-        * only a single thread will be waiting on the condition, but there
-        * are exceptions. The worst case is about 10 threads.
-        */
-       wake_up_interruptible_all(&data->futex_wait_queue);
-       return 0;
-}
-
-static long vsoc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       int rv = 0;
-       struct vsoc_device_region *region_p;
-       u32 reg_num;
-       struct vsoc_region_data *reg_data;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       region_p = vsoc_region_from_filep(filp);
-       reg_num = iminor(file_inode(filp));
-       reg_data = vsoc_dev.regions_data + reg_num;
-       switch (cmd) {
-       case VSOC_CREATE_FD_SCOPED_PERMISSION:
-               {
-                       struct fd_scoped_permission_node *node = NULL;
-
-                       node = kzalloc(sizeof(*node), GFP_KERNEL);
-                       /* We can't allocate memory for the permission */
-                       if (!node)
-                               return -ENOMEM;
-                       INIT_LIST_HEAD(&node->list);
-                       rv = do_create_fd_scoped_permission
-                               (region_p,
-                                node,
-                                (struct fd_scoped_permission_arg __user *)arg);
-                       if (!rv) {
-                               mutex_lock(&vsoc_dev.mtx);
-                               list_add(&node->list, &vsoc_dev.permissions);
-                               mutex_unlock(&vsoc_dev.mtx);
-                       } else {
-                               kfree(node);
-                               return rv;
-                       }
-               }
-               break;
-
-       case VSOC_GET_FD_SCOPED_PERMISSION:
-               {
-                       struct fd_scoped_permission_node *node =
-                           ((struct vsoc_private_data *)filp->private_data)->
-                           fd_scoped_permission_node;
-                       if (!node)
-                               return -ENOENT;
-                       if (copy_to_user
-                           ((struct fd_scoped_permission __user *)arg,
-                            &node->permission, sizeof(node->permission)))
-                               return -EFAULT;
-               }
-               break;
-
-       case VSOC_MAYBE_SEND_INTERRUPT_TO_HOST:
-               if (!atomic_xchg(reg_data->outgoing_signalled, 1)) {
-                       writel(reg_num, vsoc_dev.regs + DOORBELL);
-                       return 0;
-               } else {
-                       return -EBUSY;
-               }
-               break;
-
-       case VSOC_SEND_INTERRUPT_TO_HOST:
-               writel(reg_num, vsoc_dev.regs + DOORBELL);
-               return 0;
-       case VSOC_WAIT_FOR_INCOMING_INTERRUPT:
-               wait_event_interruptible
-                       (reg_data->interrupt_wait_queue,
-                        (atomic_read(reg_data->incoming_signalled) != 0));
-               break;
-
-       case VSOC_DESCRIBE_REGION:
-               return do_vsoc_describe_region
-                       (filp,
-                        (struct vsoc_device_region __user *)arg);
-
-       case VSOC_SELF_INTERRUPT:
-               atomic_set(reg_data->incoming_signalled, 1);
-               wake_up_interruptible(&reg_data->interrupt_wait_queue);
-               break;
-
-       case VSOC_COND_WAIT:
-               return do_vsoc_cond_wait(filp,
-                                        (struct vsoc_cond_wait __user *)arg);
-       case VSOC_COND_WAKE:
-               return do_vsoc_cond_wake(filp, arg);
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static ssize_t vsoc_read(struct file *filp, char __user *buffer, size_t len,
-                        loff_t *poffset)
-{
-       __u32 area_off;
-       const void *area_p;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       area_p = shm_off_to_virtual_addr(area_off);
-       area_p += *poffset;
-       area_len -= *poffset;
-       if (area_len <= 0)
-               return 0;
-       if (area_len < len)
-               len = area_len;
-       if (copy_to_user(buffer, area_p, len))
-               return -EFAULT;
-       *poffset += len;
-       return len;
-}
-
-static loff_t vsoc_lseek(struct file *filp, loff_t offset, int origin)
-{
-       ssize_t area_len = 0;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, NULL);
-       switch (origin) {
-       case SEEK_SET:
-               break;
-
-       case SEEK_CUR:
-               if (offset > 0 && offset + filp->f_pos < 0)
-                       return -EOVERFLOW;
-               offset += filp->f_pos;
-               break;
-
-       case SEEK_END:
-               if (offset > 0 && offset + area_len < 0)
-                       return -EOVERFLOW;
-               offset += area_len;
-               break;
-
-       case SEEK_DATA:
-               if (offset >= area_len)
-                       return -EINVAL;
-               if (offset < 0)
-                       offset = 0;
-               break;
-
-       case SEEK_HOLE:
-               /* Next hole is always the end of the region, unless offset is
-                * beyond that
-                */
-               if (offset < area_len)
-                       offset = area_len;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       if (offset < 0 || offset > area_len)
-               return -EINVAL;
-       filp->f_pos = offset;
-
-       return offset;
-}
-
-static ssize_t vsoc_write(struct file *filp, const char __user *buffer,
-                         size_t len, loff_t *poffset)
-{
-       __u32 area_off;
-       void *area_p;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       area_p = shm_off_to_virtual_addr(area_off);
-       area_p += *poffset;
-       area_len -= *poffset;
-       if (area_len <= 0)
-               return 0;
-       if (area_len < len)
-               len = area_len;
-       if (copy_from_user(area_p, buffer, len))
-               return -EFAULT;
-       *poffset += len;
-       return len;
-}
-
-static irqreturn_t vsoc_interrupt(int irq, void *region_data_v)
-{
-       struct vsoc_region_data *region_data =
-           (struct vsoc_region_data *)region_data_v;
-       int reg_num = region_data - vsoc_dev.regions_data;
-
-       if (unlikely(!region_data))
-               return IRQ_NONE;
-
-       if (unlikely(reg_num < 0 ||
-                    reg_num >= vsoc_dev.layout->region_count)) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "invalid irq @%p reg_num=0x%04x\n",
-                       region_data, reg_num);
-               return IRQ_NONE;
-       }
-       if (unlikely(vsoc_dev.regions_data + reg_num != region_data)) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "irq not aligned @%p reg_num=0x%04x\n",
-                       region_data, reg_num);
-               return IRQ_NONE;
-       }
-       wake_up_interruptible(&region_data->interrupt_wait_queue);
-       return IRQ_HANDLED;
-}
-
-static int vsoc_probe_device(struct pci_dev *pdev,
-                            const struct pci_device_id *ent)
-{
-       int result;
-       int i;
-       resource_size_t reg_size;
-       dev_t devt;
-
-       vsoc_dev.dev = pdev;
-       result = pci_enable_device(pdev);
-       if (result) {
-               dev_err(&pdev->dev,
-                       "pci_enable_device failed %s: error %d\n",
-                       pci_name(pdev), result);
-               return result;
-       }
-       vsoc_dev.enabled_device = true;
-       result = pci_request_regions(pdev, "vsoc");
-       if (result < 0) {
-               dev_err(&pdev->dev, "pci_request_regions failed\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.requested_regions = true;
-       /* Set up the control registers in BAR 0 */
-       reg_size = pci_resource_len(pdev, REGISTER_BAR);
-       if (reg_size > MAX_REGISTER_BAR_LEN)
-               vsoc_dev.regs =
-                   pci_iomap(pdev, REGISTER_BAR, MAX_REGISTER_BAR_LEN);
-       else
-               vsoc_dev.regs = pci_iomap(pdev, REGISTER_BAR, reg_size);
-
-       if (!vsoc_dev.regs) {
-               dev_err(&pdev->dev,
-                       "cannot map registers of size %zu\n",
-                      (size_t)reg_size);
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-
-       /* Map the shared memory in BAR 2 */
-       vsoc_dev.shm_phys_start = pci_resource_start(pdev, SHARED_MEMORY_BAR);
-       vsoc_dev.shm_size = pci_resource_len(pdev, SHARED_MEMORY_BAR);
-
-       dev_info(&pdev->dev, "shared memory @ DMA %pa size=0x%zx\n",
-                &vsoc_dev.shm_phys_start, vsoc_dev.shm_size);
-       vsoc_dev.kernel_mapped_shm = pci_iomap_wc(pdev, SHARED_MEMORY_BAR, 0);
-       if (!vsoc_dev.kernel_mapped_shm) {
-               dev_err(&vsoc_dev.dev->dev, "cannot iomap region\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-
-       vsoc_dev.layout = (struct vsoc_shm_layout_descriptor __force *)
-                               vsoc_dev.kernel_mapped_shm;
-       dev_info(&pdev->dev, "major_version: %d\n",
-                vsoc_dev.layout->major_version);
-       dev_info(&pdev->dev, "minor_version: %d\n",
-                vsoc_dev.layout->minor_version);
-       dev_info(&pdev->dev, "size: 0x%x\n", vsoc_dev.layout->size);
-       dev_info(&pdev->dev, "regions: %d\n", vsoc_dev.layout->region_count);
-       if (vsoc_dev.layout->major_version !=
-           CURRENT_VSOC_LAYOUT_MAJOR_VERSION) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "driver supports only major_version %d\n",
-                       CURRENT_VSOC_LAYOUT_MAJOR_VERSION);
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       result = alloc_chrdev_region(&devt, 0, vsoc_dev.layout->region_count,
-                                    VSOC_DEV_NAME);
-       if (result) {
-               dev_err(&vsoc_dev.dev->dev, "alloc_chrdev_region failed\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.major = MAJOR(devt);
-       cdev_init(&vsoc_dev.cdev, &vsoc_ops);
-       vsoc_dev.cdev.owner = THIS_MODULE;
-       result = cdev_add(&vsoc_dev.cdev, devt, vsoc_dev.layout->region_count);
-       if (result) {
-               dev_err(&vsoc_dev.dev->dev, "cdev_add error\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.cdev_added = true;
-       vsoc_dev.class = class_create(THIS_MODULE, VSOC_DEV_NAME);
-       if (IS_ERR(vsoc_dev.class)) {
-               dev_err(&vsoc_dev.dev->dev, "class_create failed\n");
-               vsoc_remove_device(pdev);
-               return PTR_ERR(vsoc_dev.class);
-       }
-       vsoc_dev.class_added = true;
-       vsoc_dev.regions = (struct vsoc_device_region __force *)
-               ((void *)vsoc_dev.layout +
-                vsoc_dev.layout->vsoc_region_desc_offset);
-       vsoc_dev.msix_entries =
-               kcalloc(vsoc_dev.layout->region_count,
-                       sizeof(vsoc_dev.msix_entries[0]), GFP_KERNEL);
-       if (!vsoc_dev.msix_entries) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "unable to allocate msix_entries\n");
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       vsoc_dev.regions_data =
-               kcalloc(vsoc_dev.layout->region_count,
-                       sizeof(vsoc_dev.regions_data[0]), GFP_KERNEL);
-       if (!vsoc_dev.regions_data) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "unable to allocate regions' data\n");
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i)
-               vsoc_dev.msix_entries[i].entry = i;
-
-       result = pci_enable_msix_exact(vsoc_dev.dev, vsoc_dev.msix_entries,
-                                      vsoc_dev.layout->region_count);
-       if (result) {
-               dev_info(&pdev->dev, "pci_enable_msix failed: %d\n", result);
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       /* Check that all regions are well formed */
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-               const struct vsoc_device_region *region = vsoc_dev.regions + i;
-
-               if (!PAGE_ALIGNED(region->region_begin_offset) ||
-                   !PAGE_ALIGNED(region->region_end_offset)) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d not aligned (%x:%x)", i,
-                               region->region_begin_offset,
-                               region->region_end_offset);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-               if (region->region_begin_offset >= region->region_end_offset ||
-                   region->region_end_offset > vsoc_dev.shm_size) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d offsets are wrong: %x %x %zx",
-                               i, region->region_begin_offset,
-                               region->region_end_offset, vsoc_dev.shm_size);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-               if (region->managed_by >= vsoc_dev.layout->region_count) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d has invalid owner: %u",
-                               i, region->managed_by);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-       }
-       vsoc_dev.msix_enabled = true;
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-               const struct vsoc_device_region *region = vsoc_dev.regions + i;
-               size_t name_sz = sizeof(vsoc_dev.regions_data[i].name) - 1;
-               const struct vsoc_signal_table_layout *h_to_g_signal_table =
-                       &region->host_to_guest_signal_table;
-               const struct vsoc_signal_table_layout *g_to_h_signal_table =
-                       &region->guest_to_host_signal_table;
-
-               vsoc_dev.regions_data[i].name[name_sz] = '\0';
-               memcpy(vsoc_dev.regions_data[i].name, region->device_name,
-                      name_sz);
-               dev_info(&pdev->dev, "region %d name=%s\n",
-                        i, vsoc_dev.regions_data[i].name);
-               init_waitqueue_head
-                       (&vsoc_dev.regions_data[i].interrupt_wait_queue);
-               init_waitqueue_head(&vsoc_dev.regions_data[i].futex_wait_queue);
-               vsoc_dev.regions_data[i].incoming_signalled =
-                       shm_off_to_virtual_addr(region->region_begin_offset) +
-                       h_to_g_signal_table->interrupt_signalled_offset;
-               vsoc_dev.regions_data[i].outgoing_signalled =
-                       shm_off_to_virtual_addr(region->region_begin_offset) +
-                       g_to_h_signal_table->interrupt_signalled_offset;
-               result = request_irq(vsoc_dev.msix_entries[i].vector,
-                                    vsoc_interrupt, 0,
-                                    vsoc_dev.regions_data[i].name,
-                                    vsoc_dev.regions_data + i);
-               if (result) {
-                       dev_info(&pdev->dev,
-                                "request_irq failed irq=%d vector=%d\n",
-                               i, vsoc_dev.msix_entries[i].vector);
-                       vsoc_remove_device(pdev);
-                       return -ENOSPC;
-               }
-               vsoc_dev.regions_data[i].irq_requested = true;
-               if (!device_create(vsoc_dev.class, NULL,
-                                  MKDEV(vsoc_dev.major, i),
-                                  NULL, vsoc_dev.regions_data[i].name)) {
-                       dev_err(&vsoc_dev.dev->dev, "device_create failed\n");
-                       vsoc_remove_device(pdev);
-                       return -EBUSY;
-               }
-               vsoc_dev.regions_data[i].device_created = true;
-       }
-       return 0;
-}
-
-/*
- * This should undo all of the allocations in the probe function in reverse
- * order.
- *
- * Notes:
- *
- *   The device may have been partially initialized, so double check
- *   that the allocations happened.
- *
- *   This function may be called multiple times, so mark resources as freed
- *   as they are deallocated.
- */
-static void vsoc_remove_device(struct pci_dev *pdev)
-{
-       int i;
-       /*
-        * pdev is the first thing to be set on probe and the last thing
-        * to be cleared here. If it's NULL then there is no cleanup.
-        */
-       if (!pdev || !vsoc_dev.dev)
-               return;
-       dev_info(&pdev->dev, "remove_device\n");
-       if (vsoc_dev.regions_data) {
-               for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-                       if (vsoc_dev.regions_data[i].device_created) {
-                               device_destroy(vsoc_dev.class,
-                                              MKDEV(vsoc_dev.major, i));
-                               vsoc_dev.regions_data[i].device_created = false;
-                       }
-                       if (vsoc_dev.regions_data[i].irq_requested)
-                               free_irq(vsoc_dev.msix_entries[i].vector, NULL);
-                       vsoc_dev.regions_data[i].irq_requested = false;
-               }
-               kfree(vsoc_dev.regions_data);
-               vsoc_dev.regions_data = NULL;
-       }
-       if (vsoc_dev.msix_enabled) {
-               pci_disable_msix(pdev);
-               vsoc_dev.msix_enabled = false;
-       }
-       kfree(vsoc_dev.msix_entries);
-       vsoc_dev.msix_entries = NULL;
-       vsoc_dev.regions = NULL;
-       if (vsoc_dev.class_added) {
-               class_destroy(vsoc_dev.class);
-               vsoc_dev.class_added = false;
-       }
-       if (vsoc_dev.cdev_added) {
-               cdev_del(&vsoc_dev.cdev);
-               vsoc_dev.cdev_added = false;
-       }
-       if (vsoc_dev.major && vsoc_dev.layout) {
-               unregister_chrdev_region(MKDEV(vsoc_dev.major, 0),
-                                        vsoc_dev.layout->region_count);
-               vsoc_dev.major = 0;
-       }
-       vsoc_dev.layout = NULL;
-       if (vsoc_dev.kernel_mapped_shm) {
-               pci_iounmap(pdev, vsoc_dev.kernel_mapped_shm);
-               vsoc_dev.kernel_mapped_shm = NULL;
-       }
-       if (vsoc_dev.regs) {
-               pci_iounmap(pdev, vsoc_dev.regs);
-               vsoc_dev.regs = NULL;
-       }
-       if (vsoc_dev.requested_regions) {
-               pci_release_regions(pdev);
-               vsoc_dev.requested_regions = false;
-       }
-       if (vsoc_dev.enabled_device) {
-               pci_disable_device(pdev);
-               vsoc_dev.enabled_device = false;
-       }
-       /* Do this last: it indicates that the device is not initialized. */
-       vsoc_dev.dev = NULL;
-}
-
-static void __exit vsoc_cleanup_module(void)
-{
-       vsoc_remove_device(vsoc_dev.dev);
-       pci_unregister_driver(&vsoc_pci_driver);
-}
-
-static int __init vsoc_init_module(void)
-{
-       int err = -ENOMEM;
-
-       INIT_LIST_HEAD(&vsoc_dev.permissions);
-       mutex_init(&vsoc_dev.mtx);
-
-       err = pci_register_driver(&vsoc_pci_driver);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
-static int vsoc_open(struct inode *inode, struct file *filp)
-{
-       /* Can't use vsoc_validate_filep because filp is still incomplete */
-       int ret = vsoc_validate_inode(inode);
-
-       if (ret)
-               return ret;
-       filp->private_data =
-               kzalloc(sizeof(struct vsoc_private_data), GFP_KERNEL);
-       if (!filp->private_data)
-               return -ENOMEM;
-       return 0;
-}
-
-static int vsoc_release(struct inode *inode, struct file *filp)
-{
-       struct vsoc_private_data *private_data = NULL;
-       struct fd_scoped_permission_node *node = NULL;
-       struct vsoc_device_region *owner_region_p = NULL;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       private_data = (struct vsoc_private_data *)filp->private_data;
-       if (!private_data)
-               return 0;
-
-       node = private_data->fd_scoped_permission_node;
-       if (node) {
-               owner_region_p = vsoc_region_from_inode(inode);
-               if (owner_region_p->managed_by != VSOC_REGION_WHOLE) {
-                       owner_region_p =
-                           &vsoc_dev.regions[owner_region_p->managed_by];
-               }
-               do_destroy_fd_scoped_permission_node(owner_region_p, node);
-               private_data->fd_scoped_permission_node = NULL;
-       }
-       kfree(private_data);
-       filp->private_data = NULL;
-
-       return 0;
-}
-
-/*
- * Returns the device relative offset and length of the area specified by the
- * fd scoped permission. If there is no fd scoped permission set, a default
- * permission covering the entire region is assumed, unless the region is owned
- * by another one, in which case the default is a permission with zero size.
- */
-static ssize_t vsoc_get_area(struct file *filp, __u32 *area_offset)
-{
-       __u32 off = 0;
-       ssize_t length = 0;
-       struct vsoc_device_region *region_p;
-       struct fd_scoped_permission *perm;
-
-       region_p = vsoc_region_from_filep(filp);
-       off = region_p->region_begin_offset;
-       perm = &((struct vsoc_private_data *)filp->private_data)->
-               fd_scoped_permission_node->permission;
-       if (perm) {
-               off += perm->begin_offset;
-               length = perm->end_offset - perm->begin_offset;
-       } else if (region_p->managed_by == VSOC_REGION_WHOLE) {
-               /* No permission set and the regions is not owned by another,
-                * default to full region access.
-                */
-               length = vsoc_device_region_size(region_p);
-       } else {
-               /* return zero length, access is denied. */
-               length = 0;
-       }
-       if (area_offset)
-               *area_offset = off;
-       return length;
-}
-
-static int vsoc_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       unsigned long len = vma->vm_end - vma->vm_start;
-       __u32 area_off;
-       phys_addr_t mem_off;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       /* Add the requested offset */
-       area_off += (vma->vm_pgoff << PAGE_SHIFT);
-       area_len -= (vma->vm_pgoff << PAGE_SHIFT);
-       if (area_len < len)
-               return -EINVAL;
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       mem_off = shm_off_to_phys_addr(area_off);
-       if (io_remap_pfn_range(vma, vma->vm_start, mem_off >> PAGE_SHIFT,
-                              len, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
-}
-
-module_init(vsoc_init_module);
-module_exit(vsoc_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Greg Hartman <ghartman@google.com>");
-MODULE_DESCRIPTION("VSoC interpretation of QEmu's ivshmem device");
-MODULE_VERSION("1.0");
index 9b19ea9d3fa144f9c81a8f3dc558cdad2d8b2a87..9a3f7c034ab49e7f141408f35f225798dc395f7c 100644 (file)
@@ -92,8 +92,8 @@ void gb_audio_manager_remove_all(void)
 
        list_for_each_entry_safe(module, next, &modules_list, list) {
                list_del(&module->list);
-               kobject_put(&module->kobj);
                ida_simple_remove(&module_id, module->id);
+               kobject_put(&module->kobj);
        }
 
        is_empty = list_empty(&modules_list);
index 9b6ea86d1dcfa6d0c16b23b1fb870292f9e68ee9..ba53959e1303b8f39778f1245c97ce0d5c0563bc 100644 (file)
@@ -2009,21 +2009,16 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
        struct ieee_param *param;
        uint ret = 0;
 
-       if (p->length < sizeof(struct ieee_param) || !p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = (struct ieee_param *)rtw_malloc(p->length);
-       if (!param) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!param)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -2054,9 +2049,6 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
                ret = -EFAULT;
 
        kfree(param);
-
-out:
-
        return ret;
 }
 
@@ -2791,26 +2783,19 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        * so, we just check hw_init_completed
        */
 
-       if (!padapter->hw_init_completed) {
-               ret = -EPERM;
-               goto out;
-       }
+       if (!padapter->hw_init_completed)
+               return -EPERM;
 
-       if (!p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = (struct ieee_param *)rtw_malloc(p->length);
-       if (!param) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!param)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -2865,7 +2850,6 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
                ret = -EFAULT;
        kfree(param);
-out:
        return ret;
 }
 #endif
index b44e902ed338cef7cd523bdde3b89e7341aec980..b6d56cfb0a190af048c0da4ef2501b02c048e241 100644 (file)
@@ -476,14 +476,13 @@ int rtl8723bs_xmit_thread(void *context)
        s32 ret;
        struct adapter *padapter;
        struct xmit_priv *pxmitpriv;
-       u8 thread_name[20] = "RTWHALXT";
-
+       u8 thread_name[20];
 
        ret = _SUCCESS;
        padapter = context;
        pxmitpriv = &padapter->xmitpriv;
 
-       rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
+       rtw_sprintf(thread_name, 20, "RTWHALXT-" ADPT_FMT, ADPT_ARG(padapter));
        thread_enter(thread_name);
 
        DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
index db6528a01229d6789152e17cd1c22af672d38eb7..9b9038e7deb1090c7bee57a4c299abaa71dcf517 100644 (file)
@@ -3373,21 +3373,16 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 
        /* down(&ieee->wx_sem); */
 
-       if (p->length < sizeof(struct ieee_param) || !p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = rtw_malloc(p->length);
-       if (param == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (param == NULL)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -3421,12 +3416,8 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 
        kfree(param);
 
-out:
-
        /* up(&ieee->wx_sem); */
-
        return ret;
-
 }
 
 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
@@ -4200,28 +4191,19 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        * so, we just check hw_init_completed
        */
 
-       if (!padapter->hw_init_completed) {
-               ret = -EPERM;
-               goto out;
-       }
-
+       if (!padapter->hw_init_completed)
+               return -EPERM;
 
-       /* if (p->length < sizeof(struct ieee_param) || !p->pointer) { */
-       if (!p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(*param))
+               return -EINVAL;
 
        param = rtw_malloc(p->length);
-       if (param == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (param == NULL)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        /* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */
@@ -4321,13 +4303,8 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
                ret = -EFAULT;
 
-
        kfree(param);
-
-out:
-
        return ret;
-
 }
 
 static int rtw_wx_set_priv(struct net_device *dev,
index 821aae8ca402fa3cac7ed2bca2f93fc3cdd62961..a0b60e7d1086731c6647777f493d9dc43fb6bfb1 100644 (file)
@@ -98,7 +98,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
 
        vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
 
-       priv->bb_pre_ed_rssi = (u8)rx_dbm + 1;
+       priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
        priv->current_rssi = priv->bb_pre_ed_rssi;
 
        skb_pull(skb, sizeof(*head));
index b94ed4e30770688891a407d1c9dba88d3110f3b8..09e55ea0bf5d5dc6af5c2010940d1aa0504bfae5 100644 (file)
@@ -1165,9 +1165,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
                conn->cid);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
                                                     scsilun_to_int(&hdr->lun));
@@ -2004,9 +2002,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                              conn->sess->se_sess, 0, DMA_NONE,
                              TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        /*
         * TASK_REASSIGN for ERL=2 / connection stays inside of
@@ -4149,6 +4145,9 @@ int iscsit_close_connection(
        iscsit_stop_nopin_response_timer(conn);
        iscsit_stop_nopin_timer(conn);
 
+       if (conn->conn_transport->iscsit_wait_conn)
+               conn->conn_transport->iscsit_wait_conn(conn);
+
        /*
         * During Connection recovery drop unacknowledged out of order
         * commands for this connection, and prepare the other commands
@@ -4231,11 +4230,6 @@ int iscsit_close_connection(
         * must wait until they have completed.
         */
        iscsit_check_conn_usage_count(conn);
-       target_sess_cmd_list_set_waiting(sess->se_sess);
-       target_wait_for_sess_cmds(sess->se_sess);
-
-       if (conn->conn_transport->iscsit_wait_conn)
-               conn->conn_transport->iscsit_wait_conn(conn);
 
        ahash_request_free(conn->conn_tx_hash);
        if (conn->conn_rx_hash) {
index ea482d4b1f00e8f03b36d8fc280f319ee03f7f4d..0ae9e60fc4d59b0056cdecfd1cbcc8391dd684f0 100644 (file)
@@ -666,6 +666,11 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 
        target_remove_from_state_list(cmd);
 
+       /*
+        * Clear struct se_cmd->se_lun before the handoff to FE.
+        */
+       cmd->se_lun = NULL;
+
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        /*
         * Determine if frontend context caller is requesting the stopping of
@@ -693,6 +698,17 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
        return cmd->se_tfo->check_stop_free(cmd);
 }
 
+static void transport_lun_remove_cmd(struct se_cmd *cmd)
+{
+       struct se_lun *lun = cmd->se_lun;
+
+       if (!lun)
+               return;
+
+       if (cmpxchg(&cmd->lun_ref_active, true, false))
+               percpu_ref_put(&lun->lun_ref);
+}
+
 static void target_complete_failure_work(struct work_struct *work)
 {
        struct se_cmd *cmd = container_of(work, struct se_cmd, work);
@@ -783,6 +799,8 @@ static void target_handle_abort(struct se_cmd *cmd)
 
        WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0);
 
+       transport_lun_remove_cmd(cmd);
+
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -1708,6 +1726,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
 
+       transport_lun_remove_cmd(se_cmd);
        transport_cmd_check_stop_to_fabric(se_cmd);
 }
 
@@ -1898,6 +1917,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
                goto queue_full;
 
 check_stop:
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2195,6 +2215,7 @@ queue_status:
                transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
                return;
        }
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -2289,6 +2310,7 @@ static void target_complete_ok_work(struct work_struct *work)
                if (ret)
                        goto queue_full;
 
+               transport_lun_remove_cmd(cmd);
                transport_cmd_check_stop_to_fabric(cmd);
                return;
        }
@@ -2314,6 +2336,7 @@ static void target_complete_ok_work(struct work_struct *work)
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2349,6 +2372,7 @@ queue_rsp:
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2384,6 +2408,7 @@ queue_status:
                break;
        }
 
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2710,6 +2735,9 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
                 */
                if (cmd->state_active)
                        target_remove_from_state_list(cmd);
+
+               if (cmd->se_lun)
+                       transport_lun_remove_cmd(cmd);
        }
        if (aborted)
                cmd->free_compl = &compl;
@@ -2781,9 +2809,6 @@ static void target_release_cmd_kref(struct kref *kref)
        struct completion *abrt_compl = se_cmd->abrt_compl;
        unsigned long flags;
 
-       if (se_cmd->lun_ref_active)
-               percpu_ref_put(&se_cmd->se_lun->lun_ref);
-
        if (se_sess) {
                spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
                list_del_init(&se_cmd->se_cmd_list);
index 4e32b6413b41ffefdef8d4abaf93d3a7f5a93097..191f9715fa9afcb3ee98fb2ee509e64a9a448b94 100644 (file)
@@ -3,6 +3,6 @@
 config AMDTEE
        tristate "AMD-TEE"
        default m
-       depends on CRYPTO_DEV_SP_PSP
+       depends on CRYPTO_DEV_SP_PSP && CRYPTO_DEV_CCP_DD
        help
          This implements AMD's Trusted Execution Environment (TEE) driver.
index ad5479f211744ffee22c0062b6013956d385c2be..7d6ecc3425081cce72e79b475ac6a7f39cf53290 100644 (file)
@@ -348,6 +348,12 @@ out:
        return ret;
 }
 
+static int tb_switch_nvm_no_read(void *priv, unsigned int offset, void *val,
+                                size_t bytes)
+{
+       return -EPERM;
+}
+
 static int tb_switch_nvm_write(void *priv, unsigned int offset, void *val,
                               size_t bytes)
 {
@@ -393,6 +399,7 @@ static struct nvmem_device *register_nvmem(struct tb_switch *sw, int id,
                config.read_only = true;
        } else {
                config.name = "nvm_non_active";
+               config.reg_read = tb_switch_nvm_no_read;
                config.reg_write = tb_switch_nvm_write;
                config.root_only = true;
        }
index d1cdd2ab8b4c00b9665f2ca4cb62107ee6e78187..d367803e2044fb9e8c4f7837866fd09260f343e9 100644 (file)
@@ -265,7 +265,6 @@ struct device *serdev_tty_port_register(struct tty_port *port,
                                        struct device *parent,
                                        struct tty_driver *drv, int idx)
 {
-       const struct tty_port_client_operations *old_ops;
        struct serdev_controller *ctrl;
        struct serport *serport;
        int ret;
@@ -284,7 +283,6 @@ struct device *serdev_tty_port_register(struct tty_port *port,
 
        ctrl->ops = &ctrl_ops;
 
-       old_ops = port->client_ops;
        port->client_ops = &client_ops;
        port->client_data = ctrl;
 
@@ -297,7 +295,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
 
 err_reset_data:
        port->client_data = NULL;
-       port->client_ops = old_ops;
+       port->client_ops = &tty_port_default_client_ops;
        serdev_controller_put(ctrl);
 
        return ERR_PTR(ret);
@@ -312,8 +310,8 @@ int serdev_tty_port_unregister(struct tty_port *port)
                return -ENODEV;
 
        serdev_controller_remove(ctrl);
-       port->client_ops = NULL;
        port->client_data = NULL;
+       port->client_ops = &tty_port_default_client_ops;
        serdev_controller_put(ctrl);
 
        return 0;
index d657aa14c3e4b588eccbfc62e899ec31b1145b1a..c33e02cbde9303110a094f8d63523197e22f9d5d 100644 (file)
@@ -446,7 +446,6 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
                port.port.line = rc;
 
        port.port.irq = irq_of_parse_and_map(np, 0);
-       port.port.irqflags = IRQF_SHARED;
        port.port.handle_irq = aspeed_vuart_handle_irq;
        port.port.iotype = UPIO_MEM;
        port.port.type = PORT_16550A;
index 0894a22fd70280eee749cb14f2101c51b051f9c8..f2a33c9082a681c3520f102fcc95d755724055e5 100644 (file)
@@ -174,7 +174,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
        struct hlist_head *h;
        struct hlist_node *n;
        struct irq_info *i;
-       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+       int ret;
 
        mutex_lock(&hash_mutex);
 
@@ -209,9 +209,8 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
                INIT_LIST_HEAD(&up->list);
                i->head = &up->list;
                spin_unlock_irq(&i->lock);
-               irq_flags |= up->port.irqflags;
                ret = request_irq(up->port.irq, serial8250_interrupt,
-                                 irq_flags, up->port.name, i);
+                                 up->port.irqflags, up->port.name, i);
                if (ret < 0)
                        serial_do_unlink(i, up);
        }
index 531ad67395e0a5488dd662a0b29f3b7293761c4a..f6687756ec5e1efd797ea7097facfb07a6466c20 100644 (file)
@@ -202,7 +202,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 
        port->type = type;
        port->uartclk = clk;
-       port->irqflags |= IRQF_SHARED;
 
        if (of_property_read_bool(np, "no-loopback-test"))
                port->flags |= UPF_SKIP_TEST;
index 430e3467aff7bf49c221401a39b2968fb8c0e7eb..0325f2e53b74507eff7b9156193e8e7dbdbcaced 100644 (file)
@@ -2177,6 +2177,10 @@ int serial8250_do_startup(struct uart_port *port)
                }
        }
 
+       /* Check if we need to have shared IRQs */
+       if (port->irq && (up->port.flags & UPF_SHARE_IRQ))
+               up->port.irqflags |= IRQF_SHARED;
+
        if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
                unsigned char iir1;
                /*
index 3bdd56a1021b26d6e74ff98ad6f0e25f25f5de08..ea12f10610b64dd46062735fc4e682213c407167 100644 (file)
@@ -286,6 +286,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
        ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
                            AR933X_UART_CS_HOST_INT_EN);
 
+       /* enable RX and TX ready overide */
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+               AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
+
        /* reenable the UART */
        ar933x_uart_rmw(up, AR933X_UART_CS_REG,
                        AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
@@ -418,6 +422,10 @@ static int ar933x_uart_startup(struct uart_port *port)
        ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
                            AR933X_UART_CS_HOST_INT_EN);
 
+       /* enable RX and TX ready overide */
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+               AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
+
        /* Enable RX interrupts */
        up->ier = AR933X_UART_INT_RX_VALID;
        ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
index c15c398c88a938bd49494f959a3cb8da5b983620..a39c87a7c2e180923ce54ff5a2b03f5c641e86f5 100644 (file)
@@ -570,7 +570,8 @@ static void atmel_stop_tx(struct uart_port *port)
        atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
        if (atmel_uart_is_half_duplex(port))
-               atmel_start_rx(port);
+               if (!atomic_read(&atmel_port->tasklet_shutdown))
+                       atmel_start_rx(port);
 
 }
 
index 19d5a4cf29a62e1685d1051a3cb4ada1d6fdcf7f..d4b81b06e0cbf79b9e52413d528023133a1bd053 100644 (file)
@@ -1373,6 +1373,7 @@ static struct console cpm_scc_uart_console = {
 
 static int __init cpm_uart_console_init(void)
 {
+       cpm_muram_init();
        register_console(&cpm_scc_uart_console);
        return 0;
 }
index 0c6c63166250d73890b020e67ac6653d3c7ae114..d337782b36486c86db6084c24975dbe0ffbf8bdc 100644 (file)
@@ -599,7 +599,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
 
        sport->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->tx_bytes);
        } else {
index 191abb18fc2a7e9208f69c1896c03106b716c270..0bd1684cabb390dff5ecd854e9553690408fac6b 100644 (file)
@@ -129,6 +129,7 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop);
 static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop);
 static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
 static void qcom_geni_serial_stop_rx(struct uart_port *uport);
+static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
 
 static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
                                        32000000, 48000000, 64000000, 80000000,
@@ -599,7 +600,7 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
        u32 irq_en;
        u32 status;
        struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
-       u32 irq_clear = S_CMD_DONE_EN;
+       u32 s_irq_status;
 
        irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
        irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
@@ -615,10 +616,19 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
                return;
 
        geni_se_cancel_s_cmd(&port->se);
-       qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
-                                       S_GENI_CMD_CANCEL, false);
+       qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
+                                       S_CMD_CANCEL_EN, true);
+       /*
+        * If timeout occurs secondary engine remains active
+        * and Abort sequence is executed.
+        */
+       s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
+       /* Flush the Rx buffer */
+       if (s_irq_status & S_RX_FIFO_LAST_EN)
+               qcom_geni_serial_handle_rx(uport, true);
+       writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
+
        status = readl(uport->membase + SE_GENI_STATUS);
-       writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
        if (status & S_GENI_CMD_ACTIVE)
                qcom_geni_serial_abort_rx(uport);
 }
index 33034b852a51fa52238d7d86c0ea7329170e967f..8de8bac9c6c7200fd84530645d79d4d7b6b80eb7 100644 (file)
@@ -692,11 +692,22 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
                                   count, DMA_TO_DEVICE);
 }
 
+static void do_handle_rx_pio(struct tegra_uart_port *tup)
+{
+       struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
+       struct tty_port *port = &tup->uport.state->port;
+
+       tegra_uart_handle_rx_pio(tup, port);
+       if (tty) {
+               tty_flip_buffer_push(port);
+               tty_kref_put(tty);
+       }
+}
+
 static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
                                      unsigned int residue)
 {
        struct tty_port *port = &tup->uport.state->port;
-       struct tty_struct *tty = tty_port_tty_get(port);
        unsigned int count;
 
        async_tx_ack(tup->rx_dma_desc);
@@ -705,11 +716,7 @@ static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
        /* If we are here, DMA is stopped */
        tegra_uart_copy_rx_to_tty(tup, port, count);
 
-       tegra_uart_handle_rx_pio(tup, port);
-       if (tty) {
-               tty_flip_buffer_push(port);
-               tty_kref_put(tty);
-       }
+       do_handle_rx_pio(tup);
 }
 
 static void tegra_uart_rx_dma_complete(void *args)
@@ -749,8 +756,10 @@ static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup)
 {
        struct dma_tx_state state;
 
-       if (!tup->rx_dma_active)
+       if (!tup->rx_dma_active) {
+               do_handle_rx_pio(tup);
                return;
+       }
 
        dmaengine_terminate_all(tup->rx_dma_chan);
        dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
@@ -816,18 +825,6 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u)
                uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
 }
 
-static void do_handle_rx_pio(struct tegra_uart_port *tup)
-{
-       struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
-       struct tty_port *port = &tup->uport.state->port;
-
-       tegra_uart_handle_rx_pio(tup, port);
-       if (tty) {
-               tty_flip_buffer_push(port);
-               tty_kref_put(tty);
-       }
-}
-
 static irqreturn_t tegra_uart_isr(int irq, void *data)
 {
        struct tegra_uart_port *tup = data;
index 044c3cbdcfa40664497d13bd00e607584eff99c7..ea80bf872f543c2883fd2fb86e66805f4f44b639 100644 (file)
@@ -52,10 +52,11 @@ static void tty_port_default_wakeup(struct tty_port *port)
        }
 }
 
-static const struct tty_port_client_operations default_client_ops = {
+const struct tty_port_client_operations tty_port_default_client_ops = {
        .receive_buf = tty_port_default_receive_buf,
        .write_wakeup = tty_port_default_wakeup,
 };
+EXPORT_SYMBOL_GPL(tty_port_default_client_ops);
 
 void tty_port_init(struct tty_port *port)
 {
@@ -68,7 +69,7 @@ void tty_port_init(struct tty_port *port)
        spin_lock_init(&port->lock);
        port->close_delay = (50 * HZ) / 100;
        port->closing_wait = (3000 * HZ) / 100;
-       port->client_ops = &default_client_ops;
+       port->client_ops = &tty_port_default_client_ops;
        kref_init(&port->kref);
 }
 EXPORT_SYMBOL(tty_port_init);
index 78732feaf65bc237ccf26fb4685198e957e6a1c1..0c50d7410b31e903139133b96260226f4f7234df 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -29,6 +30,8 @@
 #include <linux/console.h>
 #include <linux/tty_flip.h>
 
+#include <linux/sched/signal.h>
+
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)     ((c) == ' ')
 
@@ -43,6 +46,7 @@ static volatile int sel_start = -1;   /* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
 static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
 
 /* clear_selection, highlight and highlight_pointer can be called
    from interrupt (via scrollback/front) */
@@ -184,7 +188,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        char *bp, *obp;
        int i, ps, pe, multiplier;
        u32 c;
-       int mode;
+       int mode, ret = 0;
 
        poke_blanked_console();
 
@@ -210,6 +214,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (ps > pe)    /* make sel_start <= sel_end */
                swap(ps, pe);
 
+       mutex_lock(&sel_lock);
        if (sel_cons != vc_cons[fg_console].d) {
                clear_selection();
                sel_cons = vc_cons[fg_console].d;
@@ -255,9 +260,10 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                        break;
                case TIOCL_SELPOINTER:
                        highlight_pointer(pe);
-                       return 0;
+                       goto unlock;
                default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto unlock;
        }
 
        /* remove the pointer */
@@ -279,7 +285,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        else if (new_sel_start == sel_start)
        {
                if (new_sel_end == sel_end)     /* no action required */
-                       return 0;
+                       goto unlock;
                else if (new_sel_end > sel_end) /* extend to right */
                        highlight(sel_end + 2, new_sel_end);
                else                            /* contract from right */
@@ -307,7 +313,8 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (!bp) {
                printk(KERN_WARNING "selection: kmalloc() failed\n");
                clear_selection();
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto unlock;
        }
        kfree(sel_buffer);
        sel_buffer = bp;
@@ -332,7 +339,9 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                }
        }
        sel_buffer_lth = bp - sel_buffer;
-       return 0;
+unlock:
+       mutex_unlock(&sel_lock);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(set_selection_kernel);
 
@@ -350,6 +359,7 @@ int paste_selection(struct tty_struct *tty)
        unsigned int count;
        struct  tty_ldisc *ld;
        DECLARE_WAITQUEUE(wait, current);
+       int ret = 0;
 
        console_lock();
        poke_blanked_console();
@@ -361,10 +371,17 @@ int paste_selection(struct tty_struct *tty)
        tty_buffer_lock_exclusive(&vc->port);
 
        add_wait_queue(&vc->paste_wait, &wait);
+       mutex_lock(&sel_lock);
        while (sel_buffer && sel_buffer_lth > pasted) {
                set_current_state(TASK_INTERRUPTIBLE);
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
                if (tty_throttled(tty)) {
+                       mutex_unlock(&sel_lock);
                        schedule();
+                       mutex_lock(&sel_lock);
                        continue;
                }
                __set_current_state(TASK_RUNNING);
@@ -373,11 +390,12 @@ int paste_selection(struct tty_struct *tty)
                                              count);
                pasted += count;
        }
+       mutex_unlock(&sel_lock);
        remove_wait_queue(&vc->paste_wait, &wait);
        __set_current_state(TASK_RUNNING);
 
        tty_buffer_unlock_exclusive(&vc->port);
        tty_ldisc_deref(ld);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(paste_selection);
index 35d21cdb60d0b82b0c786c235b7b873409efc774..0cfbb7182b5a592aa1519a033ce92f591066c2bb 100644 (file)
@@ -936,10 +936,21 @@ static void flush_scrollback(struct vc_data *vc)
        WARN_CONSOLE_UNLOCKED();
 
        set_origin(vc);
-       if (vc->vc_sw->con_flush_scrollback)
+       if (vc->vc_sw->con_flush_scrollback) {
                vc->vc_sw->con_flush_scrollback(vc);
-       else
+       } else if (con_is_visible(vc)) {
+               /*
+                * When no con_flush_scrollback method is provided then the
+                * legacy way for flushing the scrollback buffer is to use
+                * a side effect of the con_switch method. We do it only on
+                * the foreground console as background consoles have no
+                * scrollback buffers in that case and we obviously don't
+                * want to switch to them.
+                */
+               hide_cursor(vc);
                vc->vc_sw->con_switch(vc);
+               set_cursor(vc);
+       }
 }
 
 /*
index 8b0ed139592f95bf4c42fdfbd88273dec874372e..ee6c91ef1f6cf726b8b50f40128fe1dca8effabd 100644 (file)
@@ -876,15 +876,20 @@ int vt_ioctl(struct tty_struct *tty,
                        return -EINVAL;
 
                for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                       struct vc_data *vcp;
+
                        if (!vc_cons[i].d)
                                continue;
                        console_lock();
-                       if (v.v_vlin)
-                               vc_cons[i].d->vc_scan_lines = v.v_vlin;
-                       if (v.v_clin)
-                               vc_cons[i].d->vc_font.height = v.v_clin;
-                       vc_cons[i].d->vc_resize_user = 1;
-                       vc_resize(vc_cons[i].d, v.v_cols, v.v_rows);
+                       vcp = vc_cons[i].d;
+                       if (vcp) {
+                               if (v.v_vlin)
+                                       vcp->vc_scan_lines = v.v_vlin;
+                               if (v.v_clin)
+                                       vcp->vc_font.height = v.v_clin;
+                               vcp->vc_resize_user = 1;
+                               vc_resize(vcp, v.v_cols, v.v_rows);
+                       }
                        console_unlock();
                }
                break;
index 26bc05e48d8a7414121dd348e7dfc06e6916cedc..b7918f6954344321412f550e262b6183c0d2a292 100644 (file)
@@ -256,6 +256,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                struct usb_host_interface *ifp, int num_ep,
                unsigned char *buffer, int size)
 {
+       struct usb_device *udev = to_usb_device(ddev);
        unsigned char *buffer0 = buffer;
        struct usb_endpoint_descriptor *d;
        struct usb_host_endpoint *endpoint;
@@ -297,6 +298,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
+       /* Ignore blacklisted endpoints */
+       if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) {
+               if (usb_endpoint_is_blacklisted(udev, ifp, d)) {
+                       dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n",
+                                       cfgno, inum, asnum,
+                                       d->bEndpointAddress);
+                       goto skip_to_next_endpoint_or_interface_descriptor;
+               }
+       }
+
        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
        ++ifp->desc.bNumEndpoints;
 
@@ -311,7 +322,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        j = 255;
        if (usb_endpoint_xfer_int(d)) {
                i = 1;
-               switch (to_usb_device(ddev)->speed) {
+               switch (udev->speed) {
                case USB_SPEED_SUPER_PLUS:
                case USB_SPEED_SUPER:
                case USB_SPEED_HIGH:
@@ -332,8 +343,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                        /*
                         * This quirk fixes bIntervals reported in ms.
                         */
-                       if (to_usb_device(ddev)->quirks &
-                               USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
+                       if (udev->quirks & USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
                                n = clamp(fls(d->bInterval) + 3, i, j);
                                i = j = n;
                        }
@@ -341,8 +351,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                         * This quirk fixes bIntervals reported in
                         * linear microframes.
                         */
-                       if (to_usb_device(ddev)->quirks &
-                               USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
+                       if (udev->quirks & USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
                                n = clamp(fls(d->bInterval), i, j);
                                i = j = n;
                        }
@@ -359,7 +368,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        } else if (usb_endpoint_xfer_isoc(d)) {
                i = 1;
                j = 16;
-               switch (to_usb_device(ddev)->speed) {
+               switch (udev->speed) {
                case USB_SPEED_HIGH:
                        n = 7;          /* 8 ms = 2^(7-1) uframes */
                        break;
@@ -381,8 +390,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
         * explicitly forbidden by the USB spec.  In an attempt to make
         * them usable, we will try treating them as Interrupt endpoints.
         */
-       if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
-                       usb_endpoint_xfer_bulk(d)) {
+       if (udev->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) {
                dev_warn(ddev, "config %d interface %d altsetting %d "
                    "endpoint 0x%X is Bulk; changing to Interrupt\n",
                    cfgno, inum, asnum, d->bEndpointAddress);
@@ -406,7 +414,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
 
        /* Find the highest legal maxpacket size for this endpoint */
        i = 0;          /* additional transactions per microframe */
-       switch (to_usb_device(ddev)->speed) {
+       switch (udev->speed) {
        case USB_SPEED_LOW:
                maxpacket_maxes = low_speed_maxpacket_maxes;
                break;
@@ -442,8 +450,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
         * maxpacket sizes other than 512.  High speed HCDs may not
         * be able to handle that particular bug, so let's warn...
         */
-       if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
-                       && usb_endpoint_xfer_bulk(d)) {
+       if (udev->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) {
                if (maxp != 512)
                        dev_warn(ddev, "config %d interface %d altsetting %d "
                                "bulk endpoint 0x%X has invalid maxpacket %d\n",
@@ -452,7 +459,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        }
 
        /* Parse a possible SuperSpeed endpoint companion descriptor */
-       if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER)
+       if (udev->speed >= USB_SPEED_SUPER)
                usb_parse_ss_endpoint_companion(ddev, cfgno,
                                inum, asnum, endpoint, buffer, size);
 
index 3405b146edc94f3e6fa153a769fcccccb7ee4465..1d212f82c69b45f545de3a0aba130b551b9b6177 100644 (file)
@@ -38,7 +38,9 @@
 #include "otg_whitelist.h"
 
 #define USB_VENDOR_GENESYS_LOGIC               0x05e3
+#define USB_VENDOR_SMSC                                0x0424
 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
+#define HUB_QUIRK_DISABLE_AUTOSUSPEND          0x02
 
 #define USB_TP_TRANSMISSION_DELAY      40      /* ns */
 #define USB_TP_TRANSMISSION_DELAY_MAX  65535   /* ns */
@@ -1217,11 +1219,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 #ifdef CONFIG_PM
                        udev->reset_resume = 1;
 #endif
-                       /* Don't set the change_bits when the device
-                        * was powered off.
-                        */
-                       if (test_bit(port1, hub->power_bits))
-                               set_bit(port1, hub->change_bits);
 
                } else {
                        /* The power session is gone; tell hub_wq */
@@ -1731,6 +1728,10 @@ static void hub_disconnect(struct usb_interface *intf)
        kfree(hub->buffer);
 
        pm_suspend_ignore_children(&intf->dev, false);
+
+       if (hub->quirk_disable_autosuspend)
+               usb_autopm_put_interface(intf);
+
        kref_put(&hub->kref, hub_release);
 }
 
@@ -1863,6 +1864,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
                hub->quirk_check_port_auto_suspend = 1;
 
+       if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) {
+               hub->quirk_disable_autosuspend = 1;
+               usb_autopm_get_interface(intf);
+       }
+
        if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
                return 0;
 
@@ -5599,6 +5605,10 @@ out_hdev_lock:
 }
 
 static const struct usb_device_id hub_id_table[] = {
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS,
+      .idVendor = USB_VENDOR_SMSC,
+      .bInterfaceClass = USB_CLASS_HUB,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
                        | USB_DEVICE_ID_MATCH_INT_CLASS,
       .idVendor = USB_VENDOR_GENESYS_LOGIC,
index a9e24e4b8df146b30bfab2c8857a713ff6da7c97..a97dd1ba964ee5086a57972906fcc2a7271f5cb7 100644 (file)
@@ -61,6 +61,7 @@ struct usb_hub {
        unsigned                quiescing:1;
        unsigned                disconnected:1;
        unsigned                in_reset:1;
+       unsigned                quirk_disable_autosuspend:1;
 
        unsigned                quirk_check_port_auto_suspend:1;
 
index 6b6413073584339ba9e271e17ffa63fc4f883aa4..2b24336a72e564661f6f37d1d30e0b3c4abc2070 100644 (file)
@@ -354,6 +354,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x0904, 0x6103), .driver_info =
                        USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
 
+       /* Sound Devices USBPre2 */
+       { USB_DEVICE(0x0926, 0x0202), .driver_info =
+                       USB_QUIRK_ENDPOINT_BLACKLIST },
+
        /* Keytouch QWERTY Panel keyboard */
        { USB_DEVICE(0x0926, 0x3333), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -445,6 +449,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* INTEL VALUE SSD */
        { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* novation SoundControl XL */
+       { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME },
+
        { }  /* terminating entry must be last */
 };
 
@@ -472,6 +479,39 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
        { }  /* terminating entry must be last */
 };
 
+/*
+ * Entries for blacklisted endpoints that should be ignored when parsing
+ * configuration descriptors.
+ *
+ * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
+ */
+static const struct usb_device_id usb_endpoint_blacklist[] = {
+       { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
+       { }
+};
+
+bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+               struct usb_host_interface *intf,
+               struct usb_endpoint_descriptor *epd)
+{
+       const struct usb_device_id *id;
+       unsigned int address;
+
+       for (id = usb_endpoint_blacklist; id->match_flags; ++id) {
+               if (!usb_match_device(udev, id))
+                       continue;
+
+               if (!usb_match_one_id_intf(udev, intf, id))
+                       continue;
+
+               address = id->driver_info;
+               if (address == epd->bEndpointAddress)
+                       return true;
+       }
+
+       return false;
+}
+
 static bool usb_match_any_interface(struct usb_device *udev,
                                    const struct usb_device_id *id)
 {
index cf4783cf661a86ab521155b125961ce01e3fbf2d..3ad0ee57e859fb00990bcf733112c553b25c65b1 100644 (file)
@@ -37,6 +37,9 @@ extern void usb_authorize_interface(struct usb_interface *);
 extern void usb_detect_quirks(struct usb_device *udev);
 extern void usb_detect_interface_quirks(struct usb_device *udev);
 extern void usb_release_quirk_list(void);
+extern bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+               struct usb_host_interface *intf,
+               struct usb_endpoint_descriptor *epd);
 extern int usb_remove_device(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
index 88f7d6d4ff2db1f81d4429cd1343e9e93c540903..92ed32ec160769783a14729a9aa31575057c22f3 100644 (file)
@@ -1083,11 +1083,6 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
        else
                packets = 1;    /* send one packet if length is zero. */
 
-       if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
-               dev_err(hsotg->dev, "req length > maxpacket*mc\n");
-               return;
-       }
-
        if (dir_in && index != 0)
                if (hs_ep->isochronous)
                        epsize = DXEPTSIZ_MC(packets);
@@ -1391,6 +1386,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
        req->actual = 0;
        req->status = -EINPROGRESS;
 
+       /* Don't queue ISOC request if length greater than mps*mc */
+       if (hs_ep->isochronous &&
+           req->length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
+               dev_err(hs->dev, "req length > maxpacket*mc\n");
+               return -EINVAL;
+       }
+
        /* In DDMA mode for ISOC's don't queue request if length greater
         * than descriptor limits.
         */
@@ -1632,6 +1634,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
        struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
        struct dwc2_hsotg_ep *ep;
        __le16 reply;
+       u16 status;
        int ret;
 
        dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__);
@@ -1643,11 +1646,10 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
 
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
        case USB_RECIP_DEVICE:
-               /*
-                * bit 0 => self powered
-                * bit 1 => remote wakeup
-                */
-               reply = cpu_to_le16(0);
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               status |= hsotg->remote_wakeup_allowed <<
+                         USB_DEVICE_REMOTE_WAKEUP;
+               reply = cpu_to_le16(status);
                break;
 
        case USB_RECIP_INTERFACE:
@@ -1758,7 +1760,10 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
        case USB_RECIP_DEVICE:
                switch (wValue) {
                case USB_DEVICE_REMOTE_WAKEUP:
-                       hsotg->remote_wakeup_allowed = 1;
+                       if (set)
+                               hsotg->remote_wakeup_allowed = 1;
+                       else
+                               hsotg->remote_wakeup_allowed = 0;
                        break;
 
                case USB_DEVICE_TEST_MODE:
@@ -1768,16 +1773,17 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                return -EINVAL;
 
                        hsotg->test_mode = wIndex >> 8;
-                       ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
-                       if (ret) {
-                               dev_err(hsotg->dev,
-                                       "%s: failed to send reply\n", __func__);
-                               return ret;
-                       }
                        break;
                default:
                        return -ENOENT;
                }
+
+               ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
+               if (ret) {
+                       dev_err(hsotg->dev,
+                               "%s: failed to send reply\n", __func__);
+                       return ret;
+               }
                break;
 
        case USB_RECIP_ENDPOINT:
index e56beb9d1e36c83f002052ed8ef85f75786d0b28..4a13ceaf40935abfa909495050ef37df0b40f46b 100644 (file)
@@ -256,86 +256,77 @@ static inline const char *dwc3_ep_event_string(char *str, size_t size,
        u8 epnum = event->endpoint_number;
        size_t len;
        int status;
-       int ret;
 
-       ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
+       len = scnprintf(str, size, "ep%d%s: ", epnum >> 1,
                        (epnum & 1) ? "in" : "out");
-       if (ret < 0)
-               return "UNKNOWN";
 
        status = event->status;
 
        switch (event->endpoint_event) {
        case DWC3_DEPEVT_XFERCOMPLETE:
-               len = strlen(str);
-               snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Complete (%c%c%c)",
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'L' : 'l');
 
-               len = strlen(str);
-
                if (epnum <= 1)
-                       snprintf(str + len, size - len, " [%s]",
+                       scnprintf(str + len, size - len, " [%s]",
                                        dwc3_ep0_state_string(ep0state));
                break;
        case DWC3_DEPEVT_XFERINPROGRESS:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
+               scnprintf(str + len, size - len,
+                               "Transfer In Progress [%d] (%c%c%c)",
                                event->parameters,
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'M' : 'm');
                break;
        case DWC3_DEPEVT_XFERNOTREADY:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Not Ready [%d]%s",
                                event->parameters,
                                status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
                                " (Active)" : " (Not Active)");
 
-               len = strlen(str);
-
                /* Control Endpoints */
                if (epnum <= 1) {
                        int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
 
                        switch (phase) {
                        case DEPEVT_STATUS_CONTROL_DATA:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Data Phase]");
                                break;
                        case DEPEVT_STATUS_CONTROL_STATUS:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Status Phase]");
                        }
                }
                break;
        case DWC3_DEPEVT_RXTXFIFOEVT:
-               snprintf(str + ret, size - ret, "FIFO");
+               scnprintf(str + len, size - len, "FIFO");
                break;
        case DWC3_DEPEVT_STREAMEVT:
                status = event->status;
 
                switch (status) {
                case DEPEVT_STREAMEVT_FOUND:
-                       snprintf(str + ret, size - ret, " Stream %d Found",
+                       scnprintf(str + len, size - len, " Stream %d Found",
                                        event->parameters);
                        break;
                case DEPEVT_STREAMEVT_NOTFOUND:
                default:
-                       snprintf(str + ret, size - ret, " Stream Not Found");
+                       scnprintf(str + len, size - len, " Stream Not Found");
                        break;
                }
 
                break;
        case DWC3_DEPEVT_EPCMDCMPLT:
-               snprintf(str + ret, size - ret, "Endpoint Command Complete");
+               scnprintf(str + len, size - len, "Endpoint Command Complete");
                break;
        default:
-               snprintf(str, size, "UNKNOWN");
+               scnprintf(str + len, size - len, "UNKNOWN");
        }
 
        return str;
index 1b8014ab0b25098a3d976c98cdf036646aac885f..1b7d2f9cb673a3f440677e309f1be827251693f7 100644 (file)
@@ -2429,7 +2429,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
        if (event->status & DEPEVT_STATUS_SHORT && !chain)
                return 1;
 
-       if (event->status & DEPEVT_STATUS_IOC)
+       if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
+           (trb->ctrl & DWC3_TRB_CTRL_LST))
                return 1;
 
        return 0;
index 3b4f67000315c952073068552669f2d10cc87d5d..223f72d4d9eddf2734a4148ce21cd52a358b4102 100644 (file)
@@ -437,12 +437,14 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
                val = CONFIG_USB_GADGET_VBUS_DRAW;
        if (!val)
                return 0;
-       switch (speed) {
-       case USB_SPEED_SUPER:
-               return DIV_ROUND_UP(val, 8);
-       default:
-               return DIV_ROUND_UP(val, 2);
-       }
+       if (speed < USB_SPEED_SUPER)
+               return min(val, 500U) / 2;
+       else
+               /*
+                * USB 3.x supports up to 900mA, but since 900 isn't divisible
+                * by 8 the integral division will effectively cap to 896mA.
+                */
+               return min(val, 900U) / 8;
 }
 
 static int config_buf(struct usb_configuration *config,
@@ -854,6 +856,10 @@ static int set_config(struct usb_composite_dev *cdev,
 
        /* when we return, be sure our power usage is valid */
        power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
+       if (gadget->speed < USB_SPEED_SUPER)
+               power = min(power, 500U);
+       else
+               power = min(power, 900U);
 done:
        usb_gadget_vbus_draw(gadget, power);
        if (result >= 0 && cdev->delayed_status)
@@ -2280,7 +2286,7 @@ void composite_resume(struct usb_gadget *gadget)
 {
        struct usb_composite_dev        *cdev = get_gadget_data(gadget);
        struct usb_function             *f;
-       u16                             maxpower;
+       unsigned                        maxpower;
 
        /* REVISIT:  should we have config level
         * suspend/resume callbacks?
@@ -2294,10 +2300,14 @@ void composite_resume(struct usb_gadget *gadget)
                                f->resume(f);
                }
 
-               maxpower = cdev->config->MaxPower;
+               maxpower = cdev->config->MaxPower ?
+                       cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
+               if (gadget->speed < USB_SPEED_SUPER)
+                       maxpower = min(maxpower, 500U);
+               else
+                       maxpower = min(maxpower, 900U);
 
-               usb_gadget_vbus_draw(gadget, maxpower ?
-                       maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
+               usb_gadget_vbus_draw(gadget, maxpower);
        }
 
        cdev->suspended = 0;
index 6171d28331e6d7999e5afa3a2b99e42ea1ec5168..571917677d358f4f62dbf34ee7a17a9dce0755f4 100644 (file)
@@ -1162,18 +1162,19 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
 {
        struct ffs_io_data *io_data = kiocb->private;
        struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
+       unsigned long flags;
        int value;
 
        ENTER();
 
-       spin_lock_irq(&epfile->ffs->eps_lock);
+       spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
 
        if (likely(io_data && io_data->ep && io_data->req))
                value = usb_ep_dequeue(io_data->ep, io_data->req);
        else
                value = -EINVAL;
 
-       spin_unlock_irq(&epfile->ffs->eps_lock);
+       spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
 
        return value;
 }
index 6d956f190f5ac7322cbcf8a26d444aa13e1117b5..e6d32c536781247908904b7e9252901e064fad0b 100644 (file)
@@ -361,7 +361,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
        ep = audio_dev->out_ep;
        prm = &uac->c_prm;
        config_ep_by_speed(gadget, &audio_dev->func, ep);
-       req_len = prm->max_psize;
+       req_len = ep->maxpacket;
 
        prm->ep_enabled = true;
        usb_ep_enable(ep);
@@ -379,7 +379,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
                        req->context = &prm->ureq[i];
                        req->length = req_len;
                        req->complete = u_audio_iso_complete;
-                       req->buf = prm->rbuf + i * prm->max_psize;
+                       req->buf = prm->rbuf + i * ep->maxpacket;
                }
 
                if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
@@ -430,9 +430,9 @@ int u_audio_start_playback(struct g_audio *audio_dev)
        uac->p_pktsize = min_t(unsigned int,
                                uac->p_framesize *
                                        (params->p_srate / uac->p_interval),
-                               prm->max_psize);
+                               ep->maxpacket);
 
-       if (uac->p_pktsize < prm->max_psize)
+       if (uac->p_pktsize < ep->maxpacket)
                uac->p_pktsize_residue = uac->p_framesize *
                        (params->p_srate % uac->p_interval);
        else
@@ -457,7 +457,7 @@ int u_audio_start_playback(struct g_audio *audio_dev)
                        req->context = &prm->ureq[i];
                        req->length = req_len;
                        req->complete = u_audio_iso_complete;
-                       req->buf = prm->rbuf + i * prm->max_psize;
+                       req->buf = prm->rbuf + i * ep->maxpacket;
                }
 
                if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
index f986e5c559748d43fb598753a44ffaf46e0a081c..8167d379e115ba5ae7874478f863d0b16c84f4a4 100644 (file)
@@ -561,8 +561,10 @@ static int gs_start_io(struct gs_port *port)
        port->n_read = 0;
        started = gs_start_rx(port);
 
-       /* unblock any pending writes into our circular buffer */
        if (started) {
+               gs_start_tx(port);
+               /* Unblock any pending writes into our circular buffer, in case
+                * we didn't in gs_start_tx() */
                tty_wakeup(port->port.tty);
        } else {
                gs_free_requests(ep, head, &port->read_allocated);
index 29d8e5f8bb58397ec6402f22cf723e5774f6f132..b1cfc8279c3d2d00c3ee594011124e8dd46735ba 100644 (file)
@@ -1399,7 +1399,6 @@ err:
 /**
  * xudc_stop - stops the device.
  * @gadget: pointer to the usb gadget structure
- * @driver: pointer to usb gadget driver structure
  *
  * Return: zero always
  */
index 7a3a29e5e9d29d33bec4e9ff45e50f26986dbf96..af92b2576fe91c5d497ab0aa8145aeaabd9ab5c9 100644 (file)
@@ -55,6 +55,7 @@ static u8 usb_bos_descriptor [] = {
 static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
                                     u16 wLength)
 {
+       struct xhci_port_cap *port_cap = NULL;
        int i, ssa_count;
        u32 temp;
        u16 desc_size, ssp_cap_size, ssa_size = 0;
@@ -64,16 +65,24 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
        ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
 
        /* does xhci support USB 3.1 Enhanced SuperSpeed */
-       if (xhci->usb3_rhub.min_rev >= 0x01) {
+       for (i = 0; i < xhci->num_port_caps; i++) {
+               if (xhci->port_caps[i].maj_rev == 0x03 &&
+                   xhci->port_caps[i].min_rev >= 0x01) {
+                       usb3_1 = true;
+                       port_cap = &xhci->port_caps[i];
+                       break;
+               }
+       }
+
+       if (usb3_1) {
                /* does xhci provide a PSI table for SSA speed attributes? */
-               if (xhci->usb3_rhub.psi_count) {
+               if (port_cap->psi_count) {
                        /* two SSA entries for each unique PSI ID, RX and TX */
-                       ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
+                       ssa_count = port_cap->psi_uid_count * 2;
                        ssa_size = ssa_count * sizeof(u32);
                        ssp_cap_size -= 16; /* skip copying the default SSA */
                }
                desc_size += ssp_cap_size;
-               usb3_1 = true;
        }
        memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
 
@@ -99,7 +108,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
        }
 
        /* If PSI table exists, add the custom speed attributes from it */
-       if (usb3_1 && xhci->usb3_rhub.psi_count) {
+       if (usb3_1 && port_cap->psi_count) {
                u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp;
                int offset;
 
@@ -111,7 +120,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
 
                /* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
                bm_attrib = (ssa_count - 1) & 0x1f;
-               bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
+               bm_attrib |= (port_cap->psi_uid_count - 1) << 5;
                put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
 
                if (wLength < desc_size + ssa_size)
@@ -124,8 +133,8 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
                 * USB 3.1 requires two SSA entries (RX and TX) for every link
                 */
                offset = desc_size;
-               for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
-                       psi = xhci->usb3_rhub.psi[i];
+               for (i = 0; i < port_cap->psi_count; i++) {
+                       psi = port_cap->psi[i];
                        psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
                        psi_exp = XHCI_EXT_PORT_PSIE(psi);
                        psi_mant = XHCI_EXT_PORT_PSIM(psi);
index 3b1388fa2f36e74093e2dc2abc0083cd650266c5..884c601bfa15f8d809a44bab42f11809a9c1e93c 100644 (file)
@@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        /* Allow 3 retries for everything but isoc, set CErr = 3 */
        if (!usb_endpoint_xfer_isoc(&ep->desc))
                err_count = 3;
-       /* Some devices get this wrong */
-       if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
-               max_packet = 512;
+       /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */
+       if (usb_endpoint_xfer_bulk(&ep->desc)) {
+               if (udev->speed == USB_SPEED_HIGH)
+                       max_packet = 512;
+               if (udev->speed == USB_SPEED_FULL) {
+                       max_packet = rounddown_pow_of_two(max_packet);
+                       max_packet = clamp_val(max_packet, 8, 64);
+               }
+       }
        /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
        if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                avg_trb_len = 8;
@@ -1909,17 +1915,17 @@ no_bw:
        xhci->usb3_rhub.num_ports = 0;
        xhci->num_active_eps = 0;
        kfree(xhci->usb2_rhub.ports);
-       kfree(xhci->usb2_rhub.psi);
        kfree(xhci->usb3_rhub.ports);
-       kfree(xhci->usb3_rhub.psi);
        kfree(xhci->hw_ports);
        kfree(xhci->rh_bw);
        kfree(xhci->ext_caps);
+       for (i = 0; i < xhci->num_port_caps; i++)
+               kfree(xhci->port_caps[i].psi);
+       kfree(xhci->port_caps);
+       xhci->num_port_caps = 0;
 
        xhci->usb2_rhub.ports = NULL;
-       xhci->usb2_rhub.psi = NULL;
        xhci->usb3_rhub.ports = NULL;
-       xhci->usb3_rhub.psi = NULL;
        xhci->hw_ports = NULL;
        xhci->rh_bw = NULL;
        xhci->ext_caps = NULL;
@@ -2120,6 +2126,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
        u8 major_revision, minor_revision;
        struct xhci_hub *rhub;
        struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+       struct xhci_port_cap *port_cap;
 
        temp = readl(addr);
        major_revision = XHCI_EXT_PORT_MAJOR(temp);
@@ -2154,31 +2161,39 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                /* WTF? "Valid values are ‘1’ to MaxPorts" */
                return;
 
-       rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
-       if (rhub->psi_count) {
-               rhub->psi = kcalloc_node(rhub->psi_count, sizeof(*rhub->psi),
-                                   GFP_KERNEL, dev_to_node(dev));
-               if (!rhub->psi)
-                       rhub->psi_count = 0;
+       port_cap = &xhci->port_caps[xhci->num_port_caps++];
+       if (xhci->num_port_caps > max_caps)
+               return;
+
+       port_cap->maj_rev = major_revision;
+       port_cap->min_rev = minor_revision;
+       port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);
 
-               rhub->psi_uid_count++;
-               for (i = 0; i < rhub->psi_count; i++) {
-                       rhub->psi[i] = readl(addr + 4 + i);
+       if (port_cap->psi_count) {
+               port_cap->psi = kcalloc_node(port_cap->psi_count,
+                                            sizeof(*port_cap->psi),
+                                            GFP_KERNEL, dev_to_node(dev));
+               if (!port_cap->psi)
+                       port_cap->psi_count = 0;
+
+               port_cap->psi_uid_count++;
+               for (i = 0; i < port_cap->psi_count; i++) {
+                       port_cap->psi[i] = readl(addr + 4 + i);
 
                        /* count unique ID values, two consecutive entries can
                         * have the same ID if link is assymetric
                         */
-                       if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
-                                 XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
-                               rhub->psi_uid_count++;
+                       if (i && (XHCI_EXT_PORT_PSIV(port_cap->psi[i]) !=
+                                 XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
+                               port_cap->psi_uid_count++;
 
                        xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
-                                 XHCI_EXT_PORT_PSIV(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PSIE(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PLT(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PFD(rhub->psi[i]),
-                                 XHCI_EXT_PORT_LP(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PSIM(rhub->psi[i]));
+                                 XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PLT(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PFD(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_LP(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
                }
        }
        /* cache usb2 port capabilities */
@@ -2213,6 +2228,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                        continue;
                }
                hw_port->rhub = rhub;
+               hw_port->port_cap = port_cap;
                rhub->num_ports++;
        }
        /* FIXME: Should we disable ports not in the Extended Capabilities? */
@@ -2303,6 +2319,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        if (!xhci->ext_caps)
                return -ENOMEM;
 
+       xhci->port_caps = kcalloc_node(cap_count, sizeof(*xhci->port_caps),
+                               flags, dev_to_node(dev));
+       if (!xhci->port_caps)
+               return -ENOMEM;
+
        offset = cap_start;
 
        while (offset) {
index 4917c5b033faccd0f6b9fe903dbf99cb8a47d62c..5e9b537df631bbc5bd16674674e67491e02af7bb 100644 (file)
@@ -49,6 +49,7 @@
 #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI                0x15ec
 #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI                0x15f0
 #define PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI              0x8a13
+#define PCI_DEVICE_ID_INTEL_CML_XHCI                   0xa3af
 
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4                        0x43b9
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3                        0x43ba
@@ -187,7 +188,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
-                pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) {
+                pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_CML_XHCI)) {
                xhci->quirks |= XHCI_PME_STUCK_QUIRK;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
@@ -302,6 +304,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        if (!usb_hcd_is_primary_hcd(hcd))
                return 0;
 
+       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+               xhci_pme_acpi_rtd3_enable(pdev);
+
        xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
        /* Find any debug ports */
@@ -359,9 +364,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                        HCC_MAX_PSA(xhci->hcc_params) >= 4)
                xhci->shared_hcd->can_do_streams = 1;
 
-       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
-               xhci_pme_acpi_rtd3_enable(dev);
-
        /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
        pm_runtime_put_noidle(&dev->dev);
 
index 13d8838cd552be01b145e0d2f78dc815c3ffad0b..3ecee10fdcdc7dfd697b24310de0ad3885421f10 100644 (file)
@@ -1702,12 +1702,20 @@ struct xhci_bus_state {
  * Intel Lynx Point LP xHCI host.
  */
 #define        XHCI_MAX_REXIT_TIMEOUT_MS       20
+struct xhci_port_cap {
+       u32                     *psi;   /* array of protocol speed ID entries */
+       u8                      psi_count;
+       u8                      psi_uid_count;
+       u8                      maj_rev;
+       u8                      min_rev;
+};
 
 struct xhci_port {
        __le32 __iomem          *addr;
        int                     hw_portnum;
        int                     hcd_portnum;
        struct xhci_hub         *rhub;
+       struct xhci_port_cap    *port_cap;
 };
 
 struct xhci_hub {
@@ -1719,9 +1727,6 @@ struct xhci_hub {
        /* supported prococol extended capabiliy values */
        u8                      maj_rev;
        u8                      min_rev;
-       u32                     *psi;   /* array of protocol speed ID entries */
-       u8                      psi_count;
-       u8                      psi_uid_count;
 };
 
 /* There is one xhci_hcd structure per controller */
@@ -1880,6 +1885,9 @@ struct xhci_hcd {
        /* cached usb2 extened protocol capabilites */
        u32                     *ext_caps;
        unsigned int            num_ext_caps;
+       /* cached extended protocol port capabilities */
+       struct xhci_port_cap    *port_caps;
+       unsigned int            num_port_caps;
        /* Compliance Mode Recovery Data */
        struct timer_list       comp_mode_recovery_timer;
        u32                     port_status_u0;
index dce44fbf031fb2875498632dba484fe3866ad045..dce20301e367a617277d1ae0f2489f220c4f9ee4 100644 (file)
 #define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512
 /* full speed iowarrior */
 #define USB_DEVICE_ID_CODEMERCS_IOW56  0x1503
+/* fuller speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW28  0x1504
+#define USB_DEVICE_ID_CODEMERCS_IOW28L 0x1505
+#define USB_DEVICE_ID_CODEMERCS_IOW100 0x1506
+
+/* OEMed devices */
+#define USB_DEVICE_ID_CODEMERCS_IOW24SAG       0x158a
+#define USB_DEVICE_ID_CODEMERCS_IOW56AM                0x158b
 
 /* Get a minor range for your devices from the usb maintainer */
 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -133,6 +141,11 @@ static const struct usb_device_id iowarrior_ids[] = {
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24SAG)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28L)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW100)},
        {}                      /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, iowarrior_ids);
@@ -357,6 +370,7 @@ static ssize_t iowarrior_write(struct file *file,
        }
        switch (dev->product_id) {
        case USB_DEVICE_ID_CODEMERCS_IOW24:
+       case USB_DEVICE_ID_CODEMERCS_IOW24SAG:
        case USB_DEVICE_ID_CODEMERCS_IOWPV1:
        case USB_DEVICE_ID_CODEMERCS_IOWPV2:
        case USB_DEVICE_ID_CODEMERCS_IOW40:
@@ -371,6 +385,10 @@ static ssize_t iowarrior_write(struct file *file,
                goto exit;
                break;
        case USB_DEVICE_ID_CODEMERCS_IOW56:
+       case USB_DEVICE_ID_CODEMERCS_IOW56AM:
+       case USB_DEVICE_ID_CODEMERCS_IOW28:
+       case USB_DEVICE_ID_CODEMERCS_IOW28L:
+       case USB_DEVICE_ID_CODEMERCS_IOW100:
                /* The IOW56 uses asynchronous IO and more urbs */
                if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
                        /* Wait until we are below the limit for submitted urbs */
@@ -493,6 +511,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
        switch (cmd) {
        case IOW_WRITE:
                if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
+                   dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24SAG ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
@@ -767,7 +786,11 @@ static int iowarrior_probe(struct usb_interface *interface,
                goto error;
        }
 
-       if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) {
+       if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)) {
                res = usb_find_last_int_out_endpoint(iface_desc,
                                &dev->int_out_endpoint);
                if (res) {
@@ -780,7 +803,11 @@ static int iowarrior_probe(struct usb_interface *interface,
        /* we have to check the report_size often, so remember it in the endianness suitable for our machine */
        dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
        if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
-           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
+           ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)))
                /* IOWarrior56 has wMaxPacketSize different from report size */
                dev->report_size = 7;
 
index 037e8eee737d58d1fefee1f5c4d33ccdcced7376..6153cc35aba0d71cbedaff59f8ae40ae825f43c6 100644 (file)
@@ -969,6 +969,10 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
                return  -ENXIO;
        }
 
+       /*
+        * Note that UTMI pad registers are shared by all PHYs, therefore
+        * devm_platform_ioremap_resource() can't be used here.
+        */
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                                           resource_size(res));
        if (!tegra_phy->pad_regs) {
@@ -1087,6 +1091,10 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
                return  -ENXIO;
        }
 
+       /*
+        * Note that PHY and USB controller are using shared registers,
+        * therefore devm_platform_ioremap_resource() can't be used here.
+        */
        tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
                                       resource_size(res));
        if (!tegra_phy->regs) {
index d3f420f3a083570d4d3372514c39430caa9fc8d8..c5ecdcd51ffc6742e09af4954e5c3c272233c208 100644 (file)
@@ -205,6 +205,16 @@ static int ch341_get_divisor(speed_t speed)
                        16 * speed - 16 * CH341_CLKRATE / (clk_div * (div + 1)))
                div++;
 
+       /*
+        * Prefer lower base clock (fact = 0) if even divisor.
+        *
+        * Note that this makes the receiver more tolerant to errors.
+        */
+       if (fact == 1 && div % 2 == 0) {
+               div /= 2;
+               fact = 0;
+       }
+
        return (0x100 - div) << 8 | fact << 2 | ps;
 }
 
index 79d0586e2b338019b03ddc042d9479544784c60d..172261a908d8d6d94e76996ad28e7fbf3b2cd94a 100644 (file)
@@ -448,7 +448,7 @@ static void ir_set_termios(struct tty_struct *tty,
                        usb_sndbulkpipe(udev, port->bulk_out_endpointAddress),
                        transfer_buffer, 1, &actual_length, 5000);
        if (ret || actual_length != 1) {
-               if (actual_length != 1)
+               if (!ret)
                        ret = -EIO;
                dev_err(&port->dev, "failed to change line speed: %d\n", ret);
        }
index 95bba3ba6ac67ec933215f9548df254cc44081f9..3670fda02c3460000b06be6e0d496a3eb014fbb7 100644 (file)
@@ -45,6 +45,7 @@ struct uas_dev_info {
        struct scsi_cmnd *cmnd[MAX_CMNDS];
        spinlock_t lock;
        struct work_struct work;
+       struct work_struct scan_work;      /* for async scanning */
 };
 
 enum {
@@ -114,6 +115,17 @@ out:
        spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
+static void uas_scan_work(struct work_struct *work)
+{
+       struct uas_dev_info *devinfo =
+               container_of(work, struct uas_dev_info, scan_work);
+       struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf);
+
+       dev_dbg(&devinfo->intf->dev, "starting scan\n");
+       scsi_scan_host(shost);
+       dev_dbg(&devinfo->intf->dev, "scan complete\n");
+}
+
 static void uas_add_work(struct uas_cmd_info *cmdinfo)
 {
        struct scsi_pointer *scp = (void *)cmdinfo;
@@ -982,6 +994,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        init_usb_anchor(&devinfo->data_urbs);
        spin_lock_init(&devinfo->lock);
        INIT_WORK(&devinfo->work, uas_do_work);
+       INIT_WORK(&devinfo->scan_work, uas_scan_work);
 
        result = uas_configure_endpoints(devinfo);
        if (result)
@@ -998,7 +1011,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (result)
                goto free_streams;
 
-       scsi_scan_host(shost);
+       /* Submit the delayed_work for SCSI-device scanning */
+       schedule_work(&devinfo->scan_work);
+
        return result;
 
 free_streams:
@@ -1166,6 +1181,12 @@ static void uas_disconnect(struct usb_interface *intf)
        usb_kill_anchored_urbs(&devinfo->data_urbs);
        uas_zap_pending(devinfo, DID_NO_CONNECT);
 
+       /*
+        * Prevent SCSI scanning (if it hasn't started yet)
+        * or wait for the SCSI-scanning routine to stop.
+        */
+       cancel_work_sync(&devinfo->scan_work);
+
        scsi_remove_host(shost);
        uas_free_streams(devinfo);
        scsi_host_put(shost);
index e158159671fa27a46f34c463a70c3cb461732c6b..18e205eeb9af7c8e20aec27d46d2781aebf9ae5d 100644 (file)
@@ -1414,10 +1414,6 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 
 static struct socket *get_raw_socket(int fd)
 {
-       struct {
-               struct sockaddr_ll sa;
-               char  buf[MAX_ADDR_LEN];
-       } uaddr;
        int r;
        struct socket *sock = sockfd_lookup(fd, &r);
 
@@ -1430,11 +1426,7 @@ static struct socket *get_raw_socket(int fd)
                goto err;
        }
 
-       r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, 0);
-       if (r < 0)
-               goto err;
-
-       if (uaddr.sa.sll_family != AF_PACKET) {
+       if (sock->sk->sk_family != AF_PACKET) {
                r = -EPFNOSUPPORT;
                goto err;
        }
index cec868f8db3f9645ac9bd7741f7f60e28c86bbb6..9ea2b43d4b012aebc8571b3b713011733e3d332c 100644 (file)
@@ -207,6 +207,7 @@ config DA9063_WATCHDOG
 config DA9062_WATCHDOG
        tristate "Dialog DA9062/61 Watchdog"
        depends on MFD_DA9062 || COMPILE_TEST
+       depends on I2C
        select WATCHDOG_CORE
        help
          Support for the watchdog in the DA9062 and DA9061 PMICs.
@@ -841,6 +842,7 @@ config MEDIATEK_WATCHDOG
        tristate "Mediatek SoCs watchdog support"
        depends on ARCH_MEDIATEK || COMPILE_TEST
        select WATCHDOG_CORE
+       select RESET_CONTROLLER
        help
          Say Y here to include support for the watchdog timer
          in Mediatek SoCs.
index 47eefe072b405ff055ef830e6c831464d39de6e4..0ad15d55071ce5931f8c5b381c29add6017e9683 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/jiffies.h>
 #include <linux/mfd/da9062/registers.h>
 #include <linux/mfd/da9062/core.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
 
@@ -31,6 +32,7 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
 struct da9062_watchdog {
        struct da9062 *hw;
        struct watchdog_device wdtdev;
+       bool use_sw_pm;
 };
 
 static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
@@ -95,13 +97,6 @@ static int da9062_wdt_stop(struct watchdog_device *wdd)
        struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
        int ret;
 
-       ret = da9062_reset_watchdog_timer(wdt);
-       if (ret) {
-               dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
        ret = regmap_update_bits(wdt->hw->regmap,
                                 DA9062AA_CONTROL_D,
                                 DA9062AA_TWDSCALE_MASK,
@@ -200,6 +195,8 @@ static int da9062_wdt_probe(struct platform_device *pdev)
        if (!wdt)
                return -ENOMEM;
 
+       wdt->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
+
        wdt->hw = chip;
 
        wdt->wdtdev.info = &da9062_watchdog_info;
@@ -226,6 +223,10 @@ static int da9062_wdt_probe(struct platform_device *pdev)
 static int __maybe_unused da9062_wdt_suspend(struct device *dev)
 {
        struct watchdog_device *wdd = dev_get_drvdata(dev);
+       struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
+
+       if (!wdt->use_sw_pm)
+               return 0;
 
        if (watchdog_active(wdd))
                return da9062_wdt_stop(wdd);
@@ -236,6 +237,10 @@ static int __maybe_unused da9062_wdt_suspend(struct device *dev)
 static int __maybe_unused da9062_wdt_resume(struct device *dev)
 {
        struct watchdog_device *wdd = dev_get_drvdata(dev);
+       struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
+
+       if (!wdt->use_sw_pm)
+               return 0;
 
        if (watchdog_active(wdd))
                return da9062_wdt_start(wdd);
index b069349b52f55f92005bd4d6429f2a1a95def739..3065dd670a18289df900c07c93f513c4d9c8f598 100644 (file)
@@ -54,6 +54,13 @@ module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+#define WDAT_DEFAULT_TIMEOUT   30
+
+static int timeout = WDAT_DEFAULT_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+                __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")");
+
 static int wdat_wdt_read(struct wdat_wdt *wdat,
         const struct wdat_instruction *instr, u32 *value)
 {
@@ -389,7 +396,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
 
                memset(&r, 0, sizeof(r));
                r.start = gas->address;
-               r.end = r.start + gas->access_width - 1;
+               r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
                if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
                        r.flags = IORESOURCE_MEM;
                } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
@@ -438,6 +445,22 @@ static int wdat_wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, wdat);
 
+       /*
+        * Set initial timeout so that userspace has time to configure the
+        * watchdog properly after it has opened the device. In some cases
+        * the BIOS default is too short and causes immediate reboot.
+        */
+       if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
+           timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
+               dev_warn(dev, "Invalid timeout %d given, using %d\n",
+                        timeout, WDAT_DEFAULT_TIMEOUT);
+               timeout = WDAT_DEFAULT_TIMEOUT;
+       }
+
+       ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
+       if (ret)
+               return ret;
+
        watchdog_set_nowayout(&wdat->wdd, nowayout);
        return devm_watchdog_register_device(dev, &wdat->wdd);
 }
index 70650b248de5d43dae2b4ae01d1fbebfaa6d4c10..17240c5325a30c799478f1e13df0e503dfa71c09 100644 (file)
@@ -33,7 +33,9 @@ asmlinkage __visible void xen_maybe_preempt_hcall(void)
                 * cpu.
                 */
                __this_cpu_write(xen_in_preemptible_hcall, false);
-               _cond_resched();
+               local_irq_enable();
+               cond_resched();
+               local_irq_disable();
                __this_cpu_write(xen_in_preemptible_hcall, true);
        }
 }
index 89422aa8e9d113b13b116b2459ee453762b5e582..c6c9a6a8e6c84176c3c8223827fc5fcdc9e6bd79 100644 (file)
@@ -3200,6 +3200,7 @@ int __cold open_ctree(struct super_block *sb,
        if (IS_ERR(fs_info->fs_root)) {
                err = PTR_ERR(fs_info->fs_root);
                btrfs_warn(fs_info, "failed to read fs tree: %d", err);
+               fs_info->fs_root = NULL;
                goto fail_qgroup;
        }
 
@@ -4276,6 +4277,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                cond_resched();
                spin_lock(&delayed_refs->lock);
        }
+       btrfs_qgroup_destroy_extent_records(trans);
 
        spin_unlock(&delayed_refs->lock);
 
@@ -4501,7 +4503,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
        wake_up(&fs_info->transaction_wait);
 
        btrfs_destroy_delayed_inodes(fs_info);
-       btrfs_assert_delayed_root_empty(fs_info);
 
        btrfs_destroy_marked_extents(fs_info, &cur_trans->dirty_pages,
                                     EXTENT_DIRTY);
index 0163fdd59f8f2156fd58c65e8bdbceb3ae5dec3a..a7bc66121330e1d4d428c93775c2d832041c7d18 100644 (file)
@@ -4430,6 +4430,8 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
 
        ret = alloc_reserved_file_extent(trans, 0, root_objectid, 0, owner,
                                         offset, ins, 1);
+       if (ret)
+               btrfs_pin_extent(fs_info, ins->objectid, ins->offset, 1);
        btrfs_put_block_group(block_group);
        return ret;
 }
index 7d26b4bfb2c6a400f3ccdfb5e435ae695ba8a150..1ccb3f8d528d9e84d3299b2c1fe9b7be51a77121 100644 (file)
@@ -4103,8 +4103,9 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->reada = READA_BACK;
 
-       lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
-                        &cached_state);
+       if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
+               lock_extent_bits(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
+                                &cached_state);
 
        /*
         * We want to drop from the next block forward in case this new size is
@@ -4142,7 +4143,6 @@ search_again:
                goto out;
        }
 
-       path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0)
                goto out;
@@ -4294,7 +4294,6 @@ delete:
                     root == fs_info->tree_root)) {
                        struct btrfs_ref ref = { 0 };
 
-                       btrfs_set_path_blocking(path);
                        bytes_deleted += extent_num_bytes;
 
                        btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF,
@@ -4370,11 +4369,10 @@ out:
                if (!ret && last_size > new_size)
                        last_size = new_size;
                btrfs_ordered_update_i_size(inode, last_size, NULL);
+               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start,
+                                    (u64)-1, &cached_state);
        }
 
-       unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, (u64)-1,
-                            &cached_state);
-
        btrfs_free_path(path);
        return ret;
 }
@@ -9826,6 +9824,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_key ins;
        u64 cur_offset = start;
+       u64 clear_offset = start;
        u64 i_size;
        u64 cur_bytes;
        u64 last_alloc = (u64)-1;
@@ -9860,6 +9859,15 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                                btrfs_end_transaction(trans);
                        break;
                }
+
+               /*
+                * We've reserved this space, and thus converted it from
+                * ->bytes_may_use to ->bytes_reserved.  Any error that happens
+                * from here on out we will only need to clear our reservation
+                * for the remaining unreserved area, so advance our
+                * clear_offset by our extent size.
+                */
+               clear_offset += ins.offset;
                btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 
                last_alloc = ins.offset;
@@ -9939,9 +9947,9 @@ next:
                if (own_trans)
                        btrfs_end_transaction(trans);
        }
-       if (cur_offset < end)
-               btrfs_free_reserved_data_space(inode, NULL, cur_offset,
-                       end - cur_offset + 1);
+       if (clear_offset < end)
+               btrfs_free_reserved_data_space(inode, NULL, clear_offset,
+                       end - clear_offset + 1);
        return ret;
 }
 
index ecb9fb6a6fe07f3550efe9e8bb9de463585930d3..a65f189a5b9418e17e28ef90dfb7508e13b173be 100644 (file)
@@ -679,10 +679,15 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
                }
                btrfs_start_ordered_extent(inode, ordered, 1);
                end = ordered->file_offset;
+               /*
+                * If the ordered extent had an error save the error but don't
+                * exit without waiting first for all other ordered extents in
+                * the range to complete.
+                */
                if (test_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
                        ret = -EIO;
                btrfs_put_ordered_extent(ordered);
-               if (ret || end == 0 || end == start)
+               if (end == 0 || end == start)
                        break;
                end--;
        }
index 98d9a50352d6d2bf6314cf4dc6720303e53e496e..ff1870ff3474a71f1fada625e17effa09917a074 100644 (file)
@@ -4002,3 +4002,16 @@ out:
        }
        return ret;
 }
+
+void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
+{
+       struct btrfs_qgroup_extent_record *entry;
+       struct btrfs_qgroup_extent_record *next;
+       struct rb_root *root;
+
+       root = &trans->delayed_refs.dirty_extent_root;
+       rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
+               ulist_free(entry->old_roots);
+               kfree(entry);
+       }
+}
index 236f12224d5205a591251e317cf996dd23fc1e8c..1bc65445946907c171eccc0fe1363b8ce2f0b754 100644 (file)
@@ -414,5 +414,6 @@ int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
                u64 last_snapshot);
 int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
                struct btrfs_root *root, struct extent_buffer *eb);
+void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);
 
 #endif
index 33dcc88b428ad402ed68c1dd6bbfb9dc9ee69d23..beb6c69cd1e55b7d0fb3089b4822269fb6bce38c 100644 (file)
@@ -121,6 +121,8 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
                BUG_ON(!list_empty(&transaction->list));
                WARN_ON(!RB_EMPTY_ROOT(
                                &transaction->delayed_refs.href_root.rb_root));
+               WARN_ON(!RB_EMPTY_ROOT(
+                               &transaction->delayed_refs.dirty_extent_root));
                if (transaction->delayed_refs.pending_csums)
                        btrfs_err(transaction->fs_info,
                                  "pending csums is %llu",
index db1ef144c63a52327c070f7efa2ce44acce6ba6d..2c449aed1b9209e708c049accbab3050604eb100 100644 (file)
@@ -311,8 +311,10 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
        struct extent_crypt_result ecr;
        int rc = 0;
 
-       BUG_ON(!crypt_stat || !crypt_stat->tfm
-              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
+       if (!crypt_stat || !crypt_stat->tfm
+              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
+               return -EINVAL;
+
        if (unlikely(ecryptfs_verbosity > 0)) {
                ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
                                crypt_stat->key_size);
index 1c1a56be7ea2feb35314419f79aa08ceb12dbd62..e6ac78c62ca4929efd9c22465659a7a84b6ec3ee 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Trevor S. Highland <trevor.highland@gmail.com>
- *              Tyler Hicks <tyhicks@ou.edu>
+ *              Tyler Hicks <code@tyhicks.com>
  */
 
 #ifndef ECRYPTFS_KERNEL_H
index 7d326aa0308e4da493a97f420bca1ce84cb9f272..af3eb02bbca1db90ebbd1d506fa77b3f2afbf79f 100644 (file)
@@ -1304,7 +1304,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
                printk(KERN_WARNING "Tag 1 packet contains key larger "
                       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
                rc = -EINVAL;
-               goto out;
+               goto out_free;
        }
        memcpy((*new_auth_tok)->session_key.encrypted_key,
               &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
index b8a7ce379ffe67f8ab12923a63a2bd1ceb93d156..e63259fdef2882ab5f6a9217dd9bfea95c9a7928 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
- *              Tyler Hicks <tyhicks@ou.edu>
+ *              Tyler Hicks <code@tyhicks.com>
  */
 
 #include <linux/dcache.h>
index d668e60b85b556dd27b08a345a222688b795257c..8646ba76def3416b141f8fe4f54a5812302e7886 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
- *             Tyler Hicks <tyhicks@ou.edu>
+ *             Tyler Hicks <code@tyhicks.com>
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -379,6 +379,7 @@ int __init ecryptfs_init_messaging(void)
                                        * ecryptfs_message_buf_len),
                                       GFP_KERNEL);
        if (!ecryptfs_msg_ctx_arr) {
+               kfree(ecryptfs_daemon_hash);
                rc = -ENOMEM;
                goto out;
        }
index 5f993a411251fe54635a468aa89e04ff082c3587..8fd0b3cdab4cdd55e7ad0d374064da49bb2d421e 100644 (file)
@@ -270,6 +270,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
        ext4_group_t ngroups = ext4_get_groups_count(sb);
        struct ext4_group_desc *desc;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct buffer_head *bh_p;
 
        if (block_group >= ngroups) {
                ext4_error(sb, "block_group >= groups_count - block_group = %u,"
@@ -280,7 +281,14 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
 
        group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
        offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
-       if (!sbi->s_group_desc[group_desc]) {
+       bh_p = sbi_array_rcu_deref(sbi, s_group_desc, group_desc);
+       /*
+        * sbi_array_rcu_deref returns with rcu unlocked, this is ok since
+        * the pointer being dereferenced won't be dereferenced again. By
+        * looking at the usage in add_new_gdb() the value isn't modified,
+        * just the pointer, and so it remains valid.
+        */
+       if (!bh_p) {
                ext4_error(sb, "Group descriptor not loaded - "
                           "block_group = %u, group_desc = %u, desc = %u",
                           block_group, group_desc, offset);
@@ -288,10 +296,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
        }
 
        desc = (struct ext4_group_desc *)(
-               (__u8 *)sbi->s_group_desc[group_desc]->b_data +
+               (__u8 *)bh_p->b_data +
                offset * EXT4_DESC_SIZE(sb));
        if (bh)
-               *bh = sbi->s_group_desc[group_desc];
+               *bh = bh_p;
        return desc;
 }
 
index 4441331d06cc469b332f39e58fe6cbc72f8d409e..61b37a052052b58b577ad617086dbbcdb90b48f3 100644 (file)
@@ -1400,7 +1400,7 @@ struct ext4_sb_info {
        loff_t s_bitmap_maxbytes;       /* max bytes for bitmap files */
        struct buffer_head * s_sbh;     /* Buffer containing the super block */
        struct ext4_super_block *s_es;  /* Pointer to the super block in the buffer */
-       struct buffer_head **s_group_desc;
+       struct buffer_head * __rcu *s_group_desc;
        unsigned int s_mount_opt;
        unsigned int s_mount_opt2;
        unsigned int s_mount_flags;
@@ -1462,7 +1462,7 @@ struct ext4_sb_info {
 #endif
 
        /* for buddy allocator */
-       struct ext4_group_info ***s_group_info;
+       struct ext4_group_info ** __rcu *s_group_info;
        struct inode *s_buddy_cache;
        spinlock_t s_md_lock;
        unsigned short *s_mb_offsets;
@@ -1512,7 +1512,7 @@ struct ext4_sb_info {
        unsigned int s_extent_max_zeroout_kb;
 
        unsigned int s_log_groups_per_flex;
-       struct flex_groups *s_flex_groups;
+       struct flex_groups * __rcu *s_flex_groups;
        ext4_group_t s_flex_groups_allocated;
 
        /* workqueue for reserved extent conversions (buffered io) */
@@ -1552,8 +1552,11 @@ struct ext4_sb_info {
        struct ratelimit_state s_warning_ratelimit_state;
        struct ratelimit_state s_msg_ratelimit_state;
 
-       /* Barrier between changing inodes' journal flags and writepages ops. */
-       struct percpu_rw_semaphore s_journal_flag_rwsem;
+       /*
+        * Barrier between writepages ops and changing any inode's JOURNAL_DATA
+        * or EXTENTS flag.
+        */
+       struct percpu_rw_semaphore s_writepages_rwsem;
        struct dax_device *s_daxdev;
 #ifdef CONFIG_EXT4_DEBUG
        unsigned long s_simulate_fail;
@@ -1576,6 +1579,23 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
                 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
 }
 
+/*
+ * Returns: sbi->field[index]
+ * Used to access an array element from the following sbi fields which require
+ * rcu protection to avoid dereferencing an invalid pointer due to reassignment
+ * - s_group_desc
+ * - s_group_info
+ * - s_flex_group
+ */
+#define sbi_array_rcu_deref(sbi, field, index)                            \
+({                                                                        \
+       typeof(*((sbi)->field)) _v;                                        \
+       rcu_read_lock();                                                   \
+       _v = ((typeof(_v)*)rcu_dereference((sbi)->field))[index];          \
+       rcu_read_unlock();                                                 \
+       _v;                                                                \
+})
+
 /*
  * Simulate_fail codes
  */
@@ -2730,6 +2750,7 @@ extern int ext4_generic_delete_entry(handle_t *handle,
 extern bool ext4_empty_dir(struct inode *inode);
 
 /* resize.c */
+extern void ext4_kvfree_array_rcu(void *to_free);
 extern int ext4_group_add(struct super_block *sb,
                                struct ext4_new_group_data *input);
 extern int ext4_group_extend(struct super_block *sb,
@@ -2976,13 +2997,13 @@ static inline
 struct ext4_group_info *ext4_get_group_info(struct super_block *sb,
                                            ext4_group_t group)
 {
-        struct ext4_group_info ***grp_info;
+        struct ext4_group_info **grp_info;
         long indexv, indexh;
         BUG_ON(group >= EXT4_SB(sb)->s_groups_count);
-        grp_info = EXT4_SB(sb)->s_group_info;
         indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb));
         indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1);
-        return grp_info[indexv][indexh];
+        grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv);
+        return grp_info[indexh];
 }
 
 /*
@@ -3032,7 +3053,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
                     !inode_is_locked(inode));
        down_write(&EXT4_I(inode)->i_data_sem);
        if (newsize > EXT4_I(inode)->i_disksize)
-               EXT4_I(inode)->i_disksize = newsize;
+               WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize);
        up_write(&EXT4_I(inode)->i_data_sem);
 }
 
index c66e8f9451a266669bc70a40b40b3ac1af5849d6..f95ee99091e4c55a827d4cdad01bcc89ef8b3e89 100644 (file)
@@ -328,11 +328,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
 
        percpu_counter_inc(&sbi->s_freeinodes_counter);
        if (sbi->s_log_groups_per_flex) {
-               ext4_group_t f = ext4_flex_group(sbi, block_group);
+               struct flex_groups *fg;
 
-               atomic_inc(&sbi->s_flex_groups[f].free_inodes);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups,
+                                        ext4_flex_group(sbi, block_group));
+               atomic_inc(&fg->free_inodes);
                if (is_directory)
-                       atomic_dec(&sbi->s_flex_groups[f].used_dirs);
+                       atomic_dec(&fg->used_dirs);
        }
        BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata");
        fatal = ext4_handle_dirty_metadata(handle, NULL, bh2);
@@ -368,12 +370,13 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
                            int flex_size, struct orlov_stats *stats)
 {
        struct ext4_group_desc *desc;
-       struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups;
 
        if (flex_size > 1) {
-               stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-               stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
-               stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
+               struct flex_groups *fg = sbi_array_rcu_deref(EXT4_SB(sb),
+                                                            s_flex_groups, g);
+               stats->free_inodes = atomic_read(&fg->free_inodes);
+               stats->free_clusters = atomic64_read(&fg->free_clusters);
+               stats->used_dirs = atomic_read(&fg->used_dirs);
                return;
        }
 
@@ -1054,7 +1057,8 @@ got:
                if (sbi->s_log_groups_per_flex) {
                        ext4_group_t f = ext4_flex_group(sbi, group);
 
-                       atomic_inc(&sbi->s_flex_groups[f].used_dirs);
+                       atomic_inc(&sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                       f)->used_dirs);
                }
        }
        if (ext4_has_group_desc_csum(sb)) {
@@ -1077,7 +1081,8 @@ got:
 
        if (sbi->s_log_groups_per_flex) {
                flex_group = ext4_flex_group(sbi, group);
-               atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes);
+               atomic_dec(&sbi_array_rcu_deref(sbi, s_flex_groups,
+                                               flex_group)->free_inodes);
        }
 
        inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
index e60aca791d3f19d3860085280826c0ce086e163a..fa0ff78dc033f8cda2aa123e13c177ed7728dceb 100644 (file)
@@ -2465,7 +2465,7 @@ update_disksize:
         * truncate are avoided by checking i_size under i_data_sem.
         */
        disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT;
-       if (disksize > EXT4_I(inode)->i_disksize) {
+       if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) {
                int err2;
                loff_t i_size;
 
@@ -2628,7 +2628,7 @@ static int ext4_writepages(struct address_space *mapping,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
-       percpu_down_read(&sbi->s_journal_flag_rwsem);
+       percpu_down_read(&sbi->s_writepages_rwsem);
        trace_ext4_writepages(inode, wbc);
 
        /*
@@ -2849,7 +2849,7 @@ unplug:
 out_writepages:
        trace_ext4_writepages_result(inode, wbc, ret,
                                     nr_to_write - wbc->nr_to_write);
-       percpu_up_read(&sbi->s_journal_flag_rwsem);
+       percpu_up_read(&sbi->s_writepages_rwsem);
        return ret;
 }
 
@@ -2864,13 +2864,13 @@ static int ext4_dax_writepages(struct address_space *mapping,
        if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
                return -EIO;
 
-       percpu_down_read(&sbi->s_journal_flag_rwsem);
+       percpu_down_read(&sbi->s_writepages_rwsem);
        trace_ext4_writepages(inode, wbc);
 
        ret = dax_writeback_mapping_range(mapping, sbi->s_daxdev, wbc);
        trace_ext4_writepages_result(inode, wbc, ret,
                                     nr_to_write - wbc->nr_to_write);
-       percpu_up_read(&sbi->s_journal_flag_rwsem);
+       percpu_up_read(&sbi->s_writepages_rwsem);
        return ret;
 }
 
@@ -5861,7 +5861,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                }
        }
 
-       percpu_down_write(&sbi->s_journal_flag_rwsem);
+       percpu_down_write(&sbi->s_writepages_rwsem);
        jbd2_journal_lock_updates(journal);
 
        /*
@@ -5878,7 +5878,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
                err = jbd2_journal_flush(journal);
                if (err < 0) {
                        jbd2_journal_unlock_updates(journal);
-                       percpu_up_write(&sbi->s_journal_flag_rwsem);
+                       percpu_up_write(&sbi->s_writepages_rwsem);
                        return err;
                }
                ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
@@ -5886,7 +5886,7 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        ext4_set_aops(inode);
 
        jbd2_journal_unlock_updates(journal);
-       percpu_up_write(&sbi->s_journal_flag_rwsem);
+       percpu_up_write(&sbi->s_writepages_rwsem);
 
        if (val)
                up_write(&EXT4_I(inode)->i_mmap_sem);
index f64838187559f25b859ba5acce4d0186a2c4415b..51a78eb65f3cf64744dd82a7ed0735f350a4459f 100644 (file)
@@ -2356,7 +2356,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned size;
-       struct ext4_group_info ***new_groupinfo;
+       struct ext4_group_info ***old_groupinfo, ***new_groupinfo;
 
        size = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >>
                EXT4_DESC_PER_BLOCK_BITS(sb);
@@ -2369,13 +2369,16 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
                ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
                return -ENOMEM;
        }
-       if (sbi->s_group_info) {
-               memcpy(new_groupinfo, sbi->s_group_info,
+       rcu_read_lock();
+       old_groupinfo = rcu_dereference(sbi->s_group_info);
+       if (old_groupinfo)
+               memcpy(new_groupinfo, old_groupinfo,
                       sbi->s_group_info_size * sizeof(*sbi->s_group_info));
-               kvfree(sbi->s_group_info);
-       }
-       sbi->s_group_info = new_groupinfo;
+       rcu_read_unlock();
+       rcu_assign_pointer(sbi->s_group_info, new_groupinfo);
        sbi->s_group_info_size = size / sizeof(*sbi->s_group_info);
+       if (old_groupinfo)
+               ext4_kvfree_array_rcu(old_groupinfo);
        ext4_debug("allocated s_groupinfo array for %d meta_bg's\n", 
                   sbi->s_group_info_size);
        return 0;
@@ -2387,6 +2390,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 {
        int i;
        int metalen = 0;
+       int idx = group >> EXT4_DESC_PER_BLOCK_BITS(sb);
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_group_info **meta_group_info;
        struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
@@ -2405,12 +2409,12 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
                                 "for a buddy group");
                        goto exit_meta_group_info;
                }
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] =
-                       meta_group_info;
+               rcu_read_lock();
+               rcu_dereference(sbi->s_group_info)[idx] = meta_group_info;
+               rcu_read_unlock();
        }
 
-       meta_group_info =
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)];
+       meta_group_info = sbi_array_rcu_deref(sbi, s_group_info, idx);
        i = group & (EXT4_DESC_PER_BLOCK(sb) - 1);
 
        meta_group_info[i] = kmem_cache_zalloc(cachep, GFP_NOFS);
@@ -2458,8 +2462,13 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
 exit_group_info:
        /* If a meta_group_info table has been allocated, release it now */
        if (group % EXT4_DESC_PER_BLOCK(sb) == 0) {
-               kfree(sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]);
-               sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = NULL;
+               struct ext4_group_info ***group_info;
+
+               rcu_read_lock();
+               group_info = rcu_dereference(sbi->s_group_info);
+               kfree(group_info[idx]);
+               group_info[idx] = NULL;
+               rcu_read_unlock();
        }
 exit_meta_group_info:
        return -ENOMEM;
@@ -2472,6 +2481,7 @@ static int ext4_mb_init_backend(struct super_block *sb)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        int err;
        struct ext4_group_desc *desc;
+       struct ext4_group_info ***group_info;
        struct kmem_cache *cachep;
 
        err = ext4_mb_alloc_groupinfo(sb, ngroups);
@@ -2507,11 +2517,16 @@ err_freebuddy:
        while (i-- > 0)
                kmem_cache_free(cachep, ext4_get_group_info(sb, i));
        i = sbi->s_group_info_size;
+       rcu_read_lock();
+       group_info = rcu_dereference(sbi->s_group_info);
        while (i-- > 0)
-               kfree(sbi->s_group_info[i]);
+               kfree(group_info[i]);
+       rcu_read_unlock();
        iput(sbi->s_buddy_cache);
 err_freesgi:
-       kvfree(sbi->s_group_info);
+       rcu_read_lock();
+       kvfree(rcu_dereference(sbi->s_group_info));
+       rcu_read_unlock();
        return -ENOMEM;
 }
 
@@ -2700,7 +2715,7 @@ int ext4_mb_release(struct super_block *sb)
        ext4_group_t ngroups = ext4_get_groups_count(sb);
        ext4_group_t i;
        int num_meta_group_infos;
-       struct ext4_group_info *grinfo;
+       struct ext4_group_info *grinfo, ***group_info;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
 
@@ -2719,9 +2734,12 @@ int ext4_mb_release(struct super_block *sb)
                num_meta_group_infos = (ngroups +
                                EXT4_DESC_PER_BLOCK(sb) - 1) >>
                        EXT4_DESC_PER_BLOCK_BITS(sb);
+               rcu_read_lock();
+               group_info = rcu_dereference(sbi->s_group_info);
                for (i = 0; i < num_meta_group_infos; i++)
-                       kfree(sbi->s_group_info[i]);
-               kvfree(sbi->s_group_info);
+                       kfree(group_info[i]);
+               kvfree(group_info);
+               rcu_read_unlock();
        }
        kfree(sbi->s_mb_offsets);
        kfree(sbi->s_mb_maxs);
@@ -3020,7 +3038,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                ext4_group_t flex_group = ext4_flex_group(sbi,
                                                          ac->ac_b_ex.fe_group);
                atomic64_sub(ac->ac_b_ex.fe_len,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -4918,7 +4937,8 @@ do_more:
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
                atomic64_add(count_clusters,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        /*
@@ -5075,7 +5095,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
                atomic64_add(clusters_freed,
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &sbi_array_rcu_deref(sbi, s_flex_groups,
+                                                 flex_group)->free_clusters);
        }
 
        ext4_mb_unload_buddy(&e4b);
index 89725fa425732e4933a95b60200b33f40158537d..fb6520f37135509791c35b782ba14dfe328cfa49 100644 (file)
@@ -407,6 +407,7 @@ static int free_ext_block(handle_t *handle, struct inode *inode)
 
 int ext4_ext_migrate(struct inode *inode)
 {
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        handle_t *handle;
        int retval = 0, i;
        __le32 *i_data;
@@ -431,6 +432,8 @@ int ext4_ext_migrate(struct inode *inode)
                 */
                return retval;
 
+       percpu_down_write(&sbi->s_writepages_rwsem);
+
        /*
         * Worst case we can touch the allocation bitmaps, a bgd
         * block, and a block to link in the orphan list.  We do need
@@ -441,7 +444,7 @@ int ext4_ext_migrate(struct inode *inode)
 
        if (IS_ERR(handle)) {
                retval = PTR_ERR(handle);
-               return retval;
+               goto out_unlock;
        }
        goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) *
                EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
@@ -452,7 +455,7 @@ int ext4_ext_migrate(struct inode *inode)
        if (IS_ERR(tmp_inode)) {
                retval = PTR_ERR(tmp_inode);
                ext4_journal_stop(handle);
-               return retval;
+               goto out_unlock;
        }
        i_size_write(tmp_inode, i_size_read(inode));
        /*
@@ -494,7 +497,7 @@ int ext4_ext_migrate(struct inode *inode)
                 */
                ext4_orphan_del(NULL, tmp_inode);
                retval = PTR_ERR(handle);
-               goto out;
+               goto out_tmp_inode;
        }
 
        ei = EXT4_I(inode);
@@ -576,10 +579,11 @@ err_out:
        ext4_ext_tree_init(handle, tmp_inode);
 out_stop:
        ext4_journal_stop(handle);
-out:
+out_tmp_inode:
        unlock_new_inode(tmp_inode);
        iput(tmp_inode);
-
+out_unlock:
+       percpu_up_write(&sbi->s_writepages_rwsem);
        return retval;
 }
 
@@ -589,7 +593,8 @@ out:
 int ext4_ind_migrate(struct inode *inode)
 {
        struct ext4_extent_header       *eh;
-       struct ext4_super_block         *es = EXT4_SB(inode->i_sb)->s_es;
+       struct ext4_sb_info             *sbi = EXT4_SB(inode->i_sb);
+       struct ext4_super_block         *es = sbi->s_es;
        struct ext4_inode_info          *ei = EXT4_I(inode);
        struct ext4_extent              *ex;
        unsigned int                    i, len;
@@ -613,9 +618,13 @@ int ext4_ind_migrate(struct inode *inode)
        if (test_opt(inode->i_sb, DELALLOC))
                ext4_alloc_da_blocks(inode);
 
+       percpu_down_write(&sbi->s_writepages_rwsem);
+
        handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               goto out_unlock;
+       }
 
        down_write(&EXT4_I(inode)->i_data_sem);
        ret = ext4_ext_check_inode(inode);
@@ -650,5 +659,7 @@ int ext4_ind_migrate(struct inode *inode)
 errout:
        ext4_journal_stop(handle);
        up_write(&EXT4_I(inode)->i_data_sem);
+out_unlock:
+       percpu_up_write(&sbi->s_writepages_rwsem);
        return ret;
 }
index ceff4b4b1877dd32c5c4772d05231a458035d0f8..b05ea72f38fd1981dce81b4a8cc37ec8fcad7108 100644 (file)
@@ -1511,6 +1511,7 @@ restart:
                /*
                 * We deal with the read-ahead logic here.
                 */
+               cond_resched();
                if (ra_ptr >= ra_max) {
                        /* Refill the readahead buffer */
                        ra_ptr = 0;
index 86a2500ed292f136b93f2ee75e71638567a72646..a50b51270ea9ad976c2f9da7c2cc97b8d2254eb3 100644 (file)
 
 #include "ext4_jbd2.h"
 
+struct ext4_rcu_ptr {
+       struct rcu_head rcu;
+       void *ptr;
+};
+
+static void ext4_rcu_ptr_callback(struct rcu_head *head)
+{
+       struct ext4_rcu_ptr *ptr;
+
+       ptr = container_of(head, struct ext4_rcu_ptr, rcu);
+       kvfree(ptr->ptr);
+       kfree(ptr);
+}
+
+void ext4_kvfree_array_rcu(void *to_free)
+{
+       struct ext4_rcu_ptr *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+
+       if (ptr) {
+               ptr->ptr = to_free;
+               call_rcu(&ptr->rcu, ext4_rcu_ptr_callback);
+               return;
+       }
+       synchronize_rcu();
+       kvfree(to_free);
+}
+
 int ext4_resize_begin(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -542,8 +569,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
                                brelse(gdb);
                                goto out;
                        }
-                       memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data,
-                              gdb->b_size);
+                       memcpy(gdb->b_data, sbi_array_rcu_deref(sbi,
+                               s_group_desc, j)->b_data, gdb->b_size);
                        set_buffer_uptodate(gdb);
 
                        err = ext4_handle_dirty_metadata(handle, NULL, gdb);
@@ -860,13 +887,15 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        }
        brelse(dind);
 
-       o_group_desc = EXT4_SB(sb)->s_group_desc;
+       rcu_read_lock();
+       o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
        memcpy(n_group_desc, o_group_desc,
               EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
+       rcu_read_unlock();
        n_group_desc[gdb_num] = gdb_bh;
-       EXT4_SB(sb)->s_group_desc = n_group_desc;
+       rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
        EXT4_SB(sb)->s_gdb_count++;
-       kvfree(o_group_desc);
+       ext4_kvfree_array_rcu(o_group_desc);
 
        le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
        err = ext4_handle_dirty_super(handle, sb);
@@ -909,9 +938,11 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
                return err;
        }
 
-       o_group_desc = EXT4_SB(sb)->s_group_desc;
+       rcu_read_lock();
+       o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc);
        memcpy(n_group_desc, o_group_desc,
               EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
+       rcu_read_unlock();
        n_group_desc[gdb_num] = gdb_bh;
 
        BUFFER_TRACE(gdb_bh, "get_write_access");
@@ -922,9 +953,9 @@ static int add_new_gdb_meta_bg(struct super_block *sb,
                return err;
        }
 
-       EXT4_SB(sb)->s_group_desc = n_group_desc;
+       rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc);
        EXT4_SB(sb)->s_gdb_count++;
-       kvfree(o_group_desc);
+       ext4_kvfree_array_rcu(o_group_desc);
        return err;
 }
 
@@ -1188,7 +1219,8 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
                 * use non-sparse filesystems anymore.  This is already checked above.
                 */
                if (gdb_off) {
-                       gdb_bh = sbi->s_group_desc[gdb_num];
+                       gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
+                                                    gdb_num);
                        BUFFER_TRACE(gdb_bh, "get_write_access");
                        err = ext4_journal_get_write_access(handle, gdb_bh);
 
@@ -1270,7 +1302,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb,
                /*
                 * get_write_access() has been called on gdb_bh by ext4_add_new_desc().
                 */
-               gdb_bh = sbi->s_group_desc[gdb_num];
+               gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, gdb_num);
                /* Update group descriptor block for new group */
                gdp = (struct ext4_group_desc *)(gdb_bh->b_data +
                                                 gdb_off * EXT4_DESC_SIZE(sb));
@@ -1398,11 +1430,14 @@ static void ext4_update_super(struct super_block *sb,
                   percpu_counter_read(&sbi->s_freeclusters_counter));
        if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group;
+               struct flex_groups *fg;
+
                flex_group = ext4_flex_group(sbi, group_data[0].group);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
                atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
-                            &sbi->s_flex_groups[flex_group].free_clusters);
+                            &fg->free_clusters);
                atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
-                          &sbi->s_flex_groups[flex_group].free_inodes);
+                          &fg->free_inodes);
        }
 
        /*
@@ -1497,7 +1532,8 @@ exit_journal:
                for (; gdb_num <= gdb_num_end; gdb_num++) {
                        struct buffer_head *gdb_bh;
 
-                       gdb_bh = sbi->s_group_desc[gdb_num];
+                       gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc,
+                                                    gdb_num);
                        if (old_gdb == gdb_bh->b_blocknr)
                                continue;
                        update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
index f464dff0977486a0612af2811ef0cc559ef0a71b..0c7c4adb664ec993651ae6dabba860ccd7827567 100644 (file)
@@ -1014,6 +1014,8 @@ static void ext4_put_super(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
+       struct buffer_head **group_desc;
+       struct flex_groups **flex_groups;
        int aborted = 0;
        int i, err;
 
@@ -1046,15 +1048,23 @@ static void ext4_put_super(struct super_block *sb)
        if (!sb_rdonly(sb))
                ext4_commit_super(sb, 1);
 
+       rcu_read_lock();
+       group_desc = rcu_dereference(sbi->s_group_desc);
        for (i = 0; i < sbi->s_gdb_count; i++)
-               brelse(sbi->s_group_desc[i]);
-       kvfree(sbi->s_group_desc);
-       kvfree(sbi->s_flex_groups);
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+       flex_groups = rcu_dereference(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+       rcu_read_unlock();
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
+       percpu_free_rwsem(&sbi->s_writepages_rwsem);
 #ifdef CONFIG_QUOTA
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(get_qf_name(sb, sbi, i));
@@ -2380,8 +2390,8 @@ done:
 int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct flex_groups *new_groups;
-       int size;
+       struct flex_groups **old_groups, **new_groups;
+       int size, i, j;
 
        if (!sbi->s_log_groups_per_flex)
                return 0;
@@ -2390,22 +2400,37 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
        if (size <= sbi->s_flex_groups_allocated)
                return 0;
 
-       size = roundup_pow_of_two(size * sizeof(struct flex_groups));
-       new_groups = kvzalloc(size, GFP_KERNEL);
+       new_groups = kvzalloc(roundup_pow_of_two(size *
+                             sizeof(*sbi->s_flex_groups)), GFP_KERNEL);
        if (!new_groups) {
-               ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups",
-                        size / (int) sizeof(struct flex_groups));
+               ext4_msg(sb, KERN_ERR,
+                        "not enough memory for %d flex group pointers", size);
                return -ENOMEM;
        }
-
-       if (sbi->s_flex_groups) {
-               memcpy(new_groups, sbi->s_flex_groups,
-                      (sbi->s_flex_groups_allocated *
-                       sizeof(struct flex_groups)));
-               kvfree(sbi->s_flex_groups);
+       for (i = sbi->s_flex_groups_allocated; i < size; i++) {
+               new_groups[i] = kvzalloc(roundup_pow_of_two(
+                                        sizeof(struct flex_groups)),
+                                        GFP_KERNEL);
+               if (!new_groups[i]) {
+                       for (j = sbi->s_flex_groups_allocated; j < i; j++)
+                               kvfree(new_groups[j]);
+                       kvfree(new_groups);
+                       ext4_msg(sb, KERN_ERR,
+                                "not enough memory for %d flex groups", size);
+                       return -ENOMEM;
+               }
        }
-       sbi->s_flex_groups = new_groups;
-       sbi->s_flex_groups_allocated = size / sizeof(struct flex_groups);
+       rcu_read_lock();
+       old_groups = rcu_dereference(sbi->s_flex_groups);
+       if (old_groups)
+               memcpy(new_groups, old_groups,
+                      (sbi->s_flex_groups_allocated *
+                       sizeof(struct flex_groups *)));
+       rcu_read_unlock();
+       rcu_assign_pointer(sbi->s_flex_groups, new_groups);
+       sbi->s_flex_groups_allocated = size;
+       if (old_groups)
+               ext4_kvfree_array_rcu(old_groups);
        return 0;
 }
 
@@ -2413,6 +2438,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_group_desc *gdp = NULL;
+       struct flex_groups *fg;
        ext4_group_t flex_group;
        int i, err;
 
@@ -2430,12 +2456,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
                gdp = ext4_get_group_desc(sb, i, NULL);
 
                flex_group = ext4_flex_group(sbi, i);
-               atomic_add(ext4_free_inodes_count(sb, gdp),
-                          &sbi->s_flex_groups[flex_group].free_inodes);
+               fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
+               atomic_add(ext4_free_inodes_count(sb, gdp), &fg->free_inodes);
                atomic64_add(ext4_free_group_clusters(sb, gdp),
-                            &sbi->s_flex_groups[flex_group].free_clusters);
-               atomic_add(ext4_used_dirs_count(sb, gdp),
-                          &sbi->s_flex_groups[flex_group].used_dirs);
+                            &fg->free_clusters);
+               atomic_add(ext4_used_dirs_count(sb, gdp), &fg->used_dirs);
        }
 
        return 1;
@@ -3009,7 +3034,7 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly)
                return 0;
        }
 
-#if !defined(CONFIG_QUOTA) || !defined(CONFIG_QFMT_V2)
+#if !IS_ENABLED(CONFIG_QUOTA) || !IS_ENABLED(CONFIG_QFMT_V2)
        if (!readonly && (ext4_has_feature_quota(sb) ||
                          ext4_has_feature_project(sb))) {
                ext4_msg(sb, KERN_ERR,
@@ -3634,9 +3659,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
        char *orig_data = kstrdup(data, GFP_KERNEL);
-       struct buffer_head *bh;
+       struct buffer_head *bh, **group_desc;
        struct ext4_super_block *es = NULL;
        struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+       struct flex_groups **flex_groups;
        ext4_fsblk_t block;
        ext4_fsblk_t sb_block = get_sb_block(&data);
        ext4_fsblk_t logical_sb_block;
@@ -4290,9 +4316,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        goto failed_mount;
                }
        }
-       sbi->s_group_desc = kvmalloc_array(db_count,
-                                          sizeof(struct buffer_head *),
-                                          GFP_KERNEL);
+       rcu_assign_pointer(sbi->s_group_desc,
+                          kvmalloc_array(db_count,
+                                         sizeof(struct buffer_head *),
+                                         GFP_KERNEL));
        if (sbi->s_group_desc == NULL) {
                ext4_msg(sb, KERN_ERR, "not enough memory");
                ret = -ENOMEM;
@@ -4308,14 +4335,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        for (i = 0; i < db_count; i++) {
+               struct buffer_head *bh;
+
                block = descriptor_loc(sb, logical_sb_block, i);
-               sbi->s_group_desc[i] = sb_bread_unmovable(sb, block);
-               if (!sbi->s_group_desc[i]) {
+               bh = sb_bread_unmovable(sb, block);
+               if (!bh) {
                        ext4_msg(sb, KERN_ERR,
                               "can't read group descriptor %d", i);
                        db_count = i;
                        goto failed_mount2;
                }
+               rcu_read_lock();
+               rcu_dereference(sbi->s_group_desc)[i] = bh;
+               rcu_read_unlock();
        }
        sbi->s_gdb_count = db_count;
        if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
@@ -4594,7 +4626,7 @@ no_journal:
                err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
                                          GFP_KERNEL);
        if (!err)
-               err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem);
+               err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
 
        if (err) {
                ext4_msg(sb, KERN_ERR, "insufficient memory");
@@ -4682,13 +4714,19 @@ failed_mount7:
        ext4_unregister_li_request(sb);
 failed_mount6:
        ext4_mb_release(sb);
-       if (sbi->s_flex_groups)
-               kvfree(sbi->s_flex_groups);
+       rcu_read_lock();
+       flex_groups = rcu_dereference(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+       rcu_read_unlock();
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_free_rwsem(&sbi->s_journal_flag_rwsem);
+       percpu_free_rwsem(&sbi->s_writepages_rwsem);
 failed_mount5:
        ext4_ext_release(sb);
        ext4_release_system_zone(sb);
@@ -4717,9 +4755,12 @@ failed_mount3:
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
 failed_mount2:
+       rcu_read_lock();
+       group_desc = rcu_dereference(sbi->s_group_desc);
        for (i = 0; i < db_count; i++)
-               brelse(sbi->s_group_desc[i]);
-       kvfree(sbi->s_group_desc);
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+       rcu_read_unlock();
 failed_mount:
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
index 0a5ab1a8f69a48720c6ddf213f26800ac0e58f30..bf8ed1b0b90a01ce356588ed8d9c1184ca2510f7 100644 (file)
@@ -535,42 +535,23 @@ next:
        } while (1);
 }
 
-static inline void io_worker_spin_for_work(struct io_wqe *wqe)
-{
-       int i = 0;
-
-       while (++i < 1000) {
-               if (io_wqe_run_queue(wqe))
-                       break;
-               if (need_resched())
-                       break;
-               cpu_relax();
-       }
-}
-
 static int io_wqe_worker(void *data)
 {
        struct io_worker *worker = data;
        struct io_wqe *wqe = worker->wqe;
        struct io_wq *wq = wqe->wq;
-       bool did_work;
 
        io_worker_start(wqe, worker);
 
-       did_work = false;
        while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
                set_current_state(TASK_INTERRUPTIBLE);
 loop:
-               if (did_work)
-                       io_worker_spin_for_work(wqe);
                spin_lock_irq(&wqe->lock);
                if (io_wqe_run_queue(wqe)) {
                        __set_current_state(TASK_RUNNING);
                        io_worker_handle_work(worker);
-                       did_work = true;
                        goto loop;
                }
-               did_work = false;
                /* drops the lock on success, retry */
                if (__io_worker_idle(wqe, worker)) {
                        __release(&wqe->lock);
index ccc7d84af57de1a79206181139f8471b086fc5bc..33baba4370c5f26365e9f9ffc75cba71fb364a04 100644 (file)
@@ -79,16 +79,10 @@ struct io_wq_work {
        pid_t task_pid;
 };
 
-#define INIT_IO_WORK(work, _func)                      \
-       do {                                            \
-               (work)->list.next = NULL;               \
-               (work)->func = _func;                   \
-               (work)->files = NULL;                   \
-               (work)->mm = NULL;                      \
-               (work)->creds = NULL;                   \
-               (work)->fs = NULL;                      \
-               (work)->flags = 0;                      \
-       } while (0)                                     \
+#define INIT_IO_WORK(work, _func)                              \
+       do {                                                    \
+               *(work) = (struct io_wq_work){ .func = _func }; \
+       } while (0)                                             \
 
 typedef void (get_work_fn)(struct io_wq_work *);
 typedef void (put_work_fn)(struct io_wq_work *);
index 5a826017ebb84e3701a3e0626441971a18cc778d..6a595c13e108ce2ad6a564e580fc271626623796 100644 (file)
@@ -183,17 +183,12 @@ struct fixed_file_table {
        struct file             **files;
 };
 
-enum {
-       FFD_F_ATOMIC,
-};
-
 struct fixed_file_data {
        struct fixed_file_table         *table;
        struct io_ring_ctx              *ctx;
 
        struct percpu_ref               refs;
        struct llist_head               put_llist;
-       unsigned long                   state;
        struct work_struct              ref_work;
        struct completion               done;
 };
@@ -1260,6 +1255,9 @@ static void __io_req_aux_free(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
 
+       if (req->flags & REQ_F_NEED_CLEANUP)
+               io_cleanup_req(req);
+
        kfree(req->io);
        if (req->file) {
                if (req->flags & REQ_F_FIXED_FILE)
@@ -1275,9 +1273,6 @@ static void __io_free_req(struct io_kiocb *req)
 {
        __io_req_aux_free(req);
 
-       if (req->flags & REQ_F_NEED_CLEANUP)
-               io_cleanup_req(req);
-
        if (req->flags & REQ_F_INFLIGHT) {
                struct io_ring_ctx *ctx = req->ctx;
                unsigned long flags;
@@ -1483,10 +1478,10 @@ static void io_free_req(struct io_kiocb *req)
 __attribute__((nonnull))
 static void io_put_req_find_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
 {
-       io_req_find_next(req, nxtptr);
-
-       if (refcount_dec_and_test(&req->refs))
+       if (refcount_dec_and_test(&req->refs)) {
+               io_req_find_next(req, nxtptr);
                __io_free_req(req);
+       }
 }
 
 static void io_put_req(struct io_kiocb *req)
@@ -1672,11 +1667,17 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                           long min)
+static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
+                          long min)
 {
        int iters = 0, ret = 0;
 
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
        do {
                int tmin = 0;
 
@@ -1712,21 +1713,6 @@ static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
-       return ret;
-}
-
-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                          long min)
-{
-       int ret;
-
-       /*
-        * We disallow the app entering submit/complete with polling, but we
-        * still need to lock the ring to prevent racing with polled issue
-        * that got punted to a workqueue.
-        */
-       mutex_lock(&ctx->uring_lock);
-       ret = __io_iopoll_check(ctx, nr_events, min);
        mutex_unlock(&ctx->uring_lock);
        return ret;
 }
@@ -1830,6 +1816,10 @@ static void io_iopoll_req_issued(struct io_kiocb *req)
                list_add(&req->list, &ctx->poll_list);
        else
                list_add_tail(&req->list, &ctx->poll_list);
+
+       if ((ctx->flags & IORING_SETUP_SQPOLL) &&
+           wq_has_sleeper(&ctx->sqo_wait))
+               wake_up(&ctx->sqo_wait);
 }
 
 static void io_file_put(struct io_submit_state *state)
@@ -2080,7 +2070,7 @@ static ssize_t io_import_iovec(int rw, struct io_kiocb *req,
                ssize_t ret;
                ret = import_single_range(rw, buf, sqe_len, *iovec, iter);
                *iovec = NULL;
-               return ret;
+               return ret < 0 ? ret : sqe_len;
        }
 
        if (req->io) {
@@ -2517,6 +2507,9 @@ static void io_fallocate_finish(struct io_wq_work **workptr)
        struct io_kiocb *nxt = NULL;
        int ret;
 
+       if (io_req_cancelled(req))
+               return;
+
        ret = vfs_fallocate(req->file, req->sync.mode, req->sync.off,
                                req->sync.len);
        if (ret < 0)
@@ -2904,6 +2897,7 @@ static void io_close_finish(struct io_wq_work **workptr)
        struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
        struct io_kiocb *nxt = NULL;
 
+       /* not cancellable, don't do io_req_cancelled() */
        __io_close_finish(req, &nxt);
        if (nxt)
                io_wq_assign_next(workptr, nxt);
@@ -3007,6 +3001,11 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
 
+#ifdef CONFIG_COMPAT
+       if (req->ctx->compat)
+               sr->msg_flags |= MSG_CMSG_COMPAT;
+#endif
+
        if (!io || req->opcode == IORING_OP_SEND)
                return 0;
        /* iovec is already imported */
@@ -3071,7 +3070,7 @@ static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -3159,6 +3158,11 @@ static int io_recvmsg_prep(struct io_kiocb *req,
        sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
 
+#ifdef CONFIG_COMPAT
+       if (req->ctx->compat)
+               sr->msg_flags |= MSG_CMSG_COMPAT;
+#endif
+
        if (!io || req->opcode == IORING_OP_RECV)
                return 0;
        /* iovec is already imported */
@@ -3225,7 +3229,7 @@ static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -4710,11 +4714,21 @@ static void __io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_kiocb *linked_timeout;
        struct io_kiocb *nxt = NULL;
+       const struct cred *old_creds = NULL;
        int ret;
 
 again:
        linked_timeout = io_prep_linked_timeout(req);
 
+       if (req->work.creds && req->work.creds != current_cred()) {
+               if (old_creds)
+                       revert_creds(old_creds);
+               if (old_creds == req->work.creds)
+                       old_creds = NULL; /* restored original creds */
+               else
+                       old_creds = override_creds(req->work.creds);
+       }
+
        ret = io_issue_sqe(req, sqe, &nxt, true);
 
        /*
@@ -4740,7 +4754,7 @@ punt:
 
 err:
        /* drop submission reference */
-       io_put_req(req);
+       io_put_req_find_next(req, &nxt);
 
        if (linked_timeout) {
                if (!ret)
@@ -4764,6 +4778,8 @@ done_req:
                        goto punt;
                goto again;
        }
+       if (old_creds)
+               revert_creds(old_creds);
 }
 
 static void io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
@@ -4808,7 +4824,6 @@ static inline void io_queue_link_head(struct io_kiocb *req)
 static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                          struct io_submit_state *state, struct io_kiocb **link)
 {
-       const struct cred *old_creds = NULL;
        struct io_ring_ctx *ctx = req->ctx;
        unsigned int sqe_flags;
        int ret, id;
@@ -4823,14 +4838,12 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
        id = READ_ONCE(sqe->personality);
        if (id) {
-               const struct cred *personality_creds;
-
-               personality_creds = idr_find(&ctx->personality_idr, id);
-               if (unlikely(!personality_creds)) {
+               req->work.creds = idr_find(&ctx->personality_idr, id);
+               if (unlikely(!req->work.creds)) {
                        ret = -EINVAL;
                        goto err_req;
                }
-               old_creds = override_creds(personality_creds);
+               get_cred(req->work.creds);
        }
 
        /* same numerical values with corresponding REQ_F_*, safe to copy */
@@ -4842,8 +4855,6 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 err_req:
                io_cqring_add_event(req, ret);
                io_double_put_req(req);
-               if (old_creds)
-                       revert_creds(old_creds);
                return false;
        }
 
@@ -4904,8 +4915,6 @@ err_req:
                }
        }
 
-       if (old_creds)
-               revert_creds(old_creds);
        return true;
 }
 
@@ -5086,9 +5095,8 @@ static int io_sq_thread(void *data)
        const struct cred *old_cred;
        mm_segment_t old_fs;
        DEFINE_WAIT(wait);
-       unsigned inflight;
        unsigned long timeout;
-       int ret;
+       int ret = 0;
 
        complete(&ctx->completions[1]);
 
@@ -5096,39 +5104,19 @@ static int io_sq_thread(void *data)
        set_fs(USER_DS);
        old_cred = override_creds(ctx->creds);
 
-       ret = timeout = inflight = 0;
+       timeout = jiffies + ctx->sq_thread_idle;
        while (!kthread_should_park()) {
                unsigned int to_submit;
 
-               if (inflight) {
+               if (!list_empty(&ctx->poll_list)) {
                        unsigned nr_events = 0;
 
-                       if (ctx->flags & IORING_SETUP_IOPOLL) {
-                               /*
-                                * inflight is the count of the maximum possible
-                                * entries we submitted, but it can be smaller
-                                * if we dropped some of them. If we don't have
-                                * poll entries available, then we know that we
-                                * have nothing left to poll for. Reset the
-                                * inflight count to zero in that case.
-                                */
-                               mutex_lock(&ctx->uring_lock);
-                               if (!list_empty(&ctx->poll_list))
-                                       __io_iopoll_check(ctx, &nr_events, 0);
-                               else
-                                       inflight = 0;
-                               mutex_unlock(&ctx->uring_lock);
-                       } else {
-                               /*
-                                * Normal IO, just pretend everything completed.
-                                * We don't have to poll completions for that.
-                                */
-                               nr_events = inflight;
-                       }
-
-                       inflight -= nr_events;
-                       if (!inflight)
+                       mutex_lock(&ctx->uring_lock);
+                       if (!list_empty(&ctx->poll_list))
+                               io_iopoll_getevents(ctx, &nr_events, 0);
+                       else
                                timeout = jiffies + ctx->sq_thread_idle;
+                       mutex_unlock(&ctx->uring_lock);
                }
 
                to_submit = io_sqring_entries(ctx);
@@ -5138,6 +5126,18 @@ static int io_sq_thread(void *data)
                 * to enter the kernel to reap and flush events.
                 */
                if (!to_submit || ret == -EBUSY) {
+                       /*
+                        * Drop cur_mm before scheduling, we can't hold it for
+                        * long periods (or over schedule()). Do this before
+                        * adding ourselves to the waitqueue, as the unuse/drop
+                        * may sleep.
+                        */
+                       if (cur_mm) {
+                               unuse_mm(cur_mm);
+                               mmput(cur_mm);
+                               cur_mm = NULL;
+                       }
+
                        /*
                         * We're polling. If we're within the defined idle
                         * period, then let us spin without work before going
@@ -5145,28 +5145,29 @@ static int io_sq_thread(void *data)
                         * more IO, we should wait for the application to
                         * reap events and wake us up.
                         */
-                       if (inflight ||
+                       if (!list_empty(&ctx->poll_list) ||
                            (!time_after(jiffies, timeout) && ret != -EBUSY &&
                            !percpu_ref_is_dying(&ctx->refs))) {
                                cond_resched();
                                continue;
                        }
 
+                       prepare_to_wait(&ctx->sqo_wait, &wait,
+                                               TASK_INTERRUPTIBLE);
+
                        /*
-                        * Drop cur_mm before scheduling, we can't hold it for
-                        * long periods (or over schedule()). Do this before
-                        * adding ourselves to the waitqueue, as the unuse/drop
-                        * may sleep.
+                        * While doing polled IO, before going to sleep, we need
+                        * to check if there are new reqs added to poll_list, it
+                        * is because reqs may have been punted to io worker and
+                        * will be added to poll_list later, hence check the
+                        * poll_list again.
                         */
-                       if (cur_mm) {
-                               unuse_mm(cur_mm);
-                               mmput(cur_mm);
-                               cur_mm = NULL;
+                       if ((ctx->flags & IORING_SETUP_IOPOLL) &&
+                           !list_empty_careful(&ctx->poll_list)) {
+                               finish_wait(&ctx->sqo_wait, &wait);
+                               continue;
                        }
 
-                       prepare_to_wait(&ctx->sqo_wait, &wait,
-                                               TASK_INTERRUPTIBLE);
-
                        /* Tell userspace we may need a wakeup call */
                        ctx->rings->sq_flags |= IORING_SQ_NEED_WAKEUP;
                        /* make sure to read SQ tail after writing flags */
@@ -5194,8 +5195,7 @@ static int io_sq_thread(void *data)
                mutex_lock(&ctx->uring_lock);
                ret = io_submit_sqes(ctx, to_submit, NULL, -1, &cur_mm, true);
                mutex_unlock(&ctx->uring_lock);
-               if (ret > 0)
-                       inflight += ret;
+               timeout = jiffies + ctx->sq_thread_idle;
        }
 
        set_fs(old_fs);
@@ -5600,7 +5600,6 @@ static void io_ring_file_ref_switch(struct work_struct *work)
 
        data = container_of(work, struct fixed_file_data, ref_work);
        io_ring_file_ref_flush(data);
-       percpu_ref_get(&data->refs);
        percpu_ref_switch_to_percpu(&data->refs);
 }
 
@@ -5776,8 +5775,13 @@ static void io_atomic_switch(struct percpu_ref *ref)
 {
        struct fixed_file_data *data;
 
+       /*
+        * Juggle reference to ensure we hit zero, if needed, so we can
+        * switch back to percpu mode
+        */
        data = container_of(ref, struct fixed_file_data, refs);
-       clear_bit(FFD_F_ATOMIC, &data->state);
+       percpu_ref_put(&data->refs);
+       percpu_ref_get(&data->refs);
 }
 
 static bool io_queue_file_removal(struct fixed_file_data *data,
@@ -5800,11 +5804,7 @@ static bool io_queue_file_removal(struct fixed_file_data *data,
        llist_add(&pfile->llist, &data->put_llist);
 
        if (pfile == &pfile_stack) {
-               if (!test_and_set_bit(FFD_F_ATOMIC, &data->state)) {
-                       percpu_ref_put(&data->refs);
-                       percpu_ref_switch_to_atomic(&data->refs,
-                                                       io_atomic_switch);
-               }
+               percpu_ref_switch_to_atomic(&data->refs, io_atomic_switch);
                wait_for_completion(&done);
                flush_work(&data->ref_work);
                return false;
@@ -5878,10 +5878,8 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
                up->offset++;
        }
 
-       if (ref_switch && !test_and_set_bit(FFD_F_ATOMIC, &data->state)) {
-               percpu_ref_put(&data->refs);
+       if (ref_switch)
                percpu_ref_switch_to_atomic(&data->refs, io_atomic_switch);
-       }
 
        return done ? done : err;
 }
@@ -6339,6 +6337,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
        io_sqe_buffer_unregister(ctx);
        io_sqe_files_unregister(ctx);
        io_eventfd_unregister(ctx);
+       idr_destroy(&ctx->personality_idr);
 
 #if defined(CONFIG_UNIX)
        if (ctx->ring_sock) {
@@ -6652,6 +6651,7 @@ out_fput:
        return submitted ? submitted : ret;
 }
 
+#ifdef CONFIG_PROC_FS
 static int io_uring_show_cred(int id, void *p, void *data)
 {
        const struct cred *cred = p;
@@ -6725,6 +6725,7 @@ static void io_uring_show_fdinfo(struct seq_file *m, struct file *f)
                percpu_ref_put(&ctx->refs);
        }
 }
+#endif
 
 static const struct file_operations io_uring_fops = {
        .release        = io_uring_release,
@@ -6736,7 +6737,9 @@ static const struct file_operations io_uring_fops = {
 #endif
        .poll           = io_uring_poll,
        .fasync         = io_uring_fasync,
+#ifdef CONFIG_PROC_FS
        .show_fdinfo    = io_uring_show_fdinfo,
+#endif
 };
 
 static int io_allocate_scq_urings(struct io_ring_ctx *ctx,
index 2dd848a743ed51c80efe6d475d89327790d86b3b..3dccc23cf0102337398c2c7ec99a31aa4e45b192 100644 (file)
@@ -936,8 +936,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
        char *frozen_buffer = NULL;
        unsigned long start_lock, time_lock;
 
-       if (is_handle_aborted(handle))
-               return -EROFS;
        journal = transaction->t_journal;
 
        jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
@@ -1152,8 +1150,8 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh,
        /* For undo access buffer must have data copied */
        if (undo && !jh->b_committed_data)
                goto out;
-       if (jh->b_transaction != handle->h_transaction &&
-           jh->b_next_transaction != handle->h_transaction)
+       if (READ_ONCE(jh->b_transaction) != handle->h_transaction &&
+           READ_ONCE(jh->b_next_transaction) != handle->h_transaction)
                goto out;
        /*
         * There are two reasons for the barrier here:
@@ -1189,6 +1187,9 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        int rc;
 
+       if (is_handle_aborted(handle))
+               return -EROFS;
+
        if (jbd2_write_access_granted(handle, bh, false))
                return 0;
 
@@ -1326,6 +1327,9 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        char *committed_data = NULL;
 
+       if (is_handle_aborted(handle))
+               return -EROFS;
+
        if (jbd2_write_access_granted(handle, bh, true))
                return 0;
 
@@ -2565,8 +2569,8 @@ bool __jbd2_journal_refile_buffer(struct journal_head *jh)
         * our jh reference and thus __jbd2_journal_file_buffer() must not
         * take a new one.
         */
-       jh->b_transaction = jh->b_next_transaction;
-       jh->b_next_transaction = NULL;
+       WRITE_ONCE(jh->b_transaction, jh->b_next_transaction);
+       WRITE_ONCE(jh->b_next_transaction, NULL);
        if (buffer_freed(bh))
                jlist = BJ_Forget;
        else if (jh->b_modified)
index 5a34d6c22d4cecd530cdfd1486868d577f427d9f..2144507447c5ae493230b5354bf0a0cdcd5ece2d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -722,9 +722,10 @@ pipe_release(struct inode *inode, struct file *file)
        if (file->f_mode & FMODE_WRITE)
                pipe->writers--;
 
-       if (pipe->readers || pipe->writers) {
-               wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM | EPOLLERR | EPOLLHUP);
-               wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM | EPOLLERR | EPOLLHUP);
+       /* Was that the last reader or writer, but not the other side? */
+       if (!pipe->readers != !pipe->writers) {
+               wake_up_interruptible_all(&pipe->rd_wait);
+               wake_up_interruptible_all(&pipe->wr_wait);
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
@@ -1026,8 +1027,8 @@ static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
 
 static void wake_up_partner(struct pipe_inode_info *pipe)
 {
-       wake_up_interruptible(&pipe->rd_wait);
-       wake_up_interruptible(&pipe->wr_wait);
+       wake_up_interruptible_all(&pipe->rd_wait);
+       wake_up_interruptible_all(&pipe->wr_wait);
 }
 
 static int fifo_open(struct inode *inode, struct file *filp)
@@ -1144,7 +1145,7 @@ err_rd:
 
 err_wr:
        if (!--pipe->writers)
-               wake_up_interruptible(&pipe->rd_wait);
+               wake_up_interruptible_all(&pipe->rd_wait);
        ret = -ERESTARTSYS;
        goto err;
 
@@ -1271,8 +1272,9 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
        pipe->max_usage = nr_slots;
        pipe->tail = tail;
        pipe->head = head;
-       wake_up_interruptible_all(&pipe->rd_wait);
-       wake_up_interruptible_all(&pipe->wr_wait);
+
+       /* This might have made more room for writers */
+       wake_up_interruptible(&pipe->wr_wait);
        return pipe->max_usage * PAGE_SIZE;
 
 out_revert_acct:
index fb87ad372e297d19b954a7c8187c8657a0f223cb..ef2697b78820d4634f47a258313e7ddca43daa11 100644 (file)
@@ -2,6 +2,7 @@ config ZONEFS_FS
        tristate "zonefs filesystem support"
        depends on BLOCK
        depends on BLK_DEV_ZONED
+       select FS_IOMAP
        help
          zonefs is a simple file system which exposes zones of a zoned block
          device (e.g. host-managed or host-aware SMR disk drives) as files.
index 8bc6ef82d693e06f0dc0da790db63cda8364f989..69aee3dfb6607814cb24d14ea2cdd08642a4c56a 100644 (file)
@@ -601,13 +601,13 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
        ssize_t ret;
 
        /*
-        * For async direct IOs to sequential zone files, ignore IOCB_NOWAIT
+        * For async direct IOs to sequential zone files, refuse IOCB_NOWAIT
         * as this can cause write reordering (e.g. the first aio gets EAGAIN
         * on the inode lock but the second goes through but is now unaligned).
         */
-       if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && !is_sync_kiocb(iocb)
-           && (iocb->ki_flags & IOCB_NOWAIT))
-               iocb->ki_flags &= ~IOCB_NOWAIT;
+       if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && !is_sync_kiocb(iocb) &&
+           (iocb->ki_flags & IOCB_NOWAIT))
+               return -EOPNOTSUPP;
 
        if (iocb->ki_flags & IOCB_NOWAIT) {
                if (!inode_trylock(inode))
index 5867777bb7d0fb2107080c7026804447f9dab9fb..8e8be989c2a6f56e9d503580493b8ddb8b7593a5 100644 (file)
@@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(void))
+ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_get_gpe_device(u32 gpe_index,
index a2583c2bc0548c8da7ec53f6c535c636661e8ced..4defed58ea338fd61e789751af92c5a04b04088a 100644 (file)
@@ -532,11 +532,12 @@ typedef u64 acpi_integer;
         strnlen (a, ACPI_NAMESEG_SIZE) == ACPI_NAMESEG_SIZE)
 
 /*
- * Algorithm to obtain access bit width.
+ * Algorithm to obtain access bit or byte width.
  * Can be used with access_width of struct acpi_generic_address and access_size of
  * struct acpi_resource_generic_register.
  */
 #define ACPI_ACCESS_BIT_WIDTH(size)     (1 << ((size) + 2))
+#define ACPI_ACCESS_BYTE_WIDTH(size)    (1 << ((size) - 1))
 
 /*******************************************************************************
  *
index 9d53f545a3d5e171620346245176e0c36d77afa7..69f4164d647769456ed8a7c53e1c46d8f6be9664 100644 (file)
@@ -70,6 +70,7 @@ struct vgic_global {
 
        /* Hardware has GICv4? */
        bool                    has_gicv4;
+       bool                    has_gicv4_1;
 
        /* GIC system register CPU interface */
        struct static_key_false gicv3_cpuif;
@@ -230,6 +231,9 @@ struct vgic_dist {
        /* distributor enabled */
        bool                    enabled;
 
+       /* Wants SGIs without active state */
+       bool                    nassgireq;
+
        struct vgic_irq         *spis;
 
        struct vgic_io_device   dist_iodev;
index 053ea4b519887eaf7b61baee51657eb0ea2930f1..10455b2bbbb4a18f69e58621964354824b3f1787 100644 (file)
@@ -524,7 +524,7 @@ struct request_queue {
        unsigned int            sg_reserved_size;
        int                     node;
 #ifdef CONFIG_BLK_DEV_IO_TRACE
-       struct blk_trace        *blk_trace;
+       struct blk_trace __rcu  *blk_trace;
        struct mutex            blk_trace_mutex;
 #endif
        /*
index 7bb2d8de9f308e367bcda4a5484f67483f8fc8e5..3b6ff5902edce65c9ec1dc1ccb0497b0ac521194 100644 (file)
@@ -51,9 +51,13 @@ void __trace_note_message(struct blk_trace *, struct blkcg *blkcg, const char *f
  **/
 #define blk_add_cgroup_trace_msg(q, cg, fmt, ...)                      \
        do {                                                            \
-               struct blk_trace *bt = (q)->blk_trace;                  \
+               struct blk_trace *bt;                                   \
+                                                                       \
+               rcu_read_lock();                                        \
+               bt = rcu_dereference((q)->blk_trace);                   \
                if (unlikely(bt))                                       \
                        __trace_note_message(bt, cg, fmt, ##__VA_ARGS__);\
+               rcu_read_unlock();                                      \
        } while (0)
 #define blk_add_trace_msg(q, fmt, ...)                                 \
        blk_add_cgroup_trace_msg(q, NULL, fmt, ##__VA_ARGS__)
@@ -61,10 +65,14 @@ void __trace_note_message(struct blk_trace *, struct blkcg *blkcg, const char *f
 
 static inline bool blk_trace_note_message_enabled(struct request_queue *q)
 {
-       struct blk_trace *bt = q->blk_trace;
-       if (likely(!bt))
-               return false;
-       return bt->act_mask & BLK_TC_NOTIFY;
+       struct blk_trace *bt;
+       bool ret;
+
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
+       ret = bt && (bt->act_mask & BLK_TC_NOTIFY);
+       rcu_read_unlock();
+       return ret;
 }
 
 extern void blk_add_driver_data(struct request_queue *q, struct request *rq,
index 7e18c939663e71309ef058b27097658a11cd97c3..d11e183fcb542101417180b12e8cce8a84b8b0df 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+#define BOOTCONFIG_MAGIC       "#BOOTCONFIG\n"
+#define BOOTCONFIG_MAGIC_LEN   12
+
 /* XBC tree node */
 struct xbc_node {
        u16 next;
index 11083d84eb23ead8fcc62ca6277b9c904fe9bb6f..df2475be134aa5e53c4daa28fd819741282a7c99 100644 (file)
@@ -248,15 +248,6 @@ typedef struct compat_siginfo {
        } _sifields;
 } compat_siginfo_t;
 
-/*
- * These functions operate on 32- or 64-bit specs depending on
- * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
- */
-extern int compat_get_timespec(struct timespec *, const void __user *);
-extern int compat_put_timespec(const struct timespec *, void __user *);
-extern int compat_get_timeval(struct timeval *, const void __user *);
-extern int compat_put_timeval(const struct timeval *, void __user *);
-
 struct compat_iovec {
        compat_uptr_t   iov_base;
        compat_size_t   iov_len;
@@ -416,26 +407,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const kernel_siginf
 int get_compat_sigevent(struct sigevent *event,
                const struct compat_sigevent __user *u_event);
 
-static inline int old_timeval32_compare(struct old_timeval32 *lhs,
-                                       struct old_timeval32 *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_usec - rhs->tv_usec;
-}
-
-static inline int old_timespec32_compare(struct old_timespec32 *lhs,
-                                       struct old_timespec32 *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_nsec - rhs->tv_nsec;
-}
-
 extern int get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat);
 
 /*
index cd41f209043f6dabe779040724883e14b75129c6..875f71132b1425b494ba9eb538f29543cb857753 100644 (file)
@@ -492,7 +492,7 @@ struct hid_report_enum {
 };
 
 #define HID_MIN_BUFFER_SIZE    64              /* make sure there is at least a packet size of space */
-#define HID_MAX_BUFFER_SIZE    4096            /* 4kb */
+#define HID_MAX_BUFFER_SIZE    8192            /* 8kb */
 #define HID_CONTROL_FIFO_SIZE  256             /* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE   64
 
index 93338fd54af884fbada4211197f801a4284594d9..33d37960231441d63a1d7a3d611da916734fc2cd 100644 (file)
@@ -22,19 +22,23 @@ extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn);
 int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
                               unsigned int data_len);
 
+#if IS_ENABLED(CONFIG_NF_NAT)
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
+#else
+#define icmpv6_ndo_send icmpv6_send
+#endif
+
 #else
 
 static inline void icmpv6_send(struct sk_buff *skb,
                               u8 type, u8 code, __u32 info)
 {
-
 }
-#endif
 
-#if IS_ENABLED(CONFIG_NF_NAT)
-void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
-#else
-#define icmpv6_ndo_send icmpv6_send
+static inline void icmpv6_ndo_send(struct sk_buff *skb,
+                                  u8 type, u8 code, __u32 info)
+{
+}
 #endif
 
 extern int                             icmpv6_init(void);
index 94f047a8a845424f5ea34a73f8adb5b2ef5d57b9..d7c403d0dd27d84ecdc8d8b094739e32b85968e2 100644 (file)
@@ -122,7 +122,7 @@ static inline int intel_svm_unbind_mm(struct device *dev, int pasid)
        BUG();
 }
 
-static int intel_svm_is_pasid_valid(struct device *dev, int pasid)
+static inline int intel_svm_is_pasid_valid(struct device *dev, int pasid)
 {
        return -EINVAL;
 }
index b9850f5f1906a2539df8c4c49737dba12248eecf..fa8c0455c3523316e00a6eaaaed4bf4347ccdb42 100644 (file)
@@ -32,6 +32,8 @@ struct gic_kvm_info {
        struct resource vctrl;
        /* vlpi support */
        bool            has_v4;
+       /* rvpeid support */
+       bool            has_v4_1;
 };
 
 const struct gic_kvm_info *gic_get_kvm_info(void);
index 83439bfb6c5b0eb258a3d1cec2cf6beb98e11abf..590cdbeba9d5cd52c86d29229a16860592625111 100644 (file)
@@ -57,6 +57,7 @@
 #define GICD_SPENDSGIR                 0x0F20
 
 #define GICD_CTLR_RWP                  (1U << 31)
+#define GICD_CTLR_nASSGIreq            (1U << 8)
 #define GICD_CTLR_DS                   (1U << 6)
 #define GICD_CTLR_ARE_NS               (1U << 4)
 #define GICD_CTLR_ENABLE_G1A           (1U << 1)
@@ -90,6 +91,7 @@
 #define GICD_TYPER_ESPIS(typer)                                                \
        (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
 
+#define GICD_TYPER2_nASSGIcap          (1U << 8)
 #define GICD_TYPER2_VIL                        (1U << 7)
 #define GICD_TYPER2_VID                        GENMASK(4, 0)
 
 #define GICR_VPENDBASER_4_1_VGRP1EN    (1ULL << 58)
 #define GICR_VPENDBASER_4_1_VPEID      GENMASK_ULL(15, 0)
 
+#define GICR_VSGIR                     0x0080
+
+#define GICR_VSGIR_VPEID               GENMASK(15, 0)
+
+#define GICR_VSGIPENDR                 0x0088
+
+#define GICR_VSGIPENDR_BUSY            (1U << 31)
+#define GICR_VSGIPENDR_PENDING         GENMASK(15, 0)
+
 /*
  * ITS registers, offsets from ITS_base
  */
 
 #define GITS_TRANSLATER                        0x10040
 
+#define GITS_SGIR                      0x20020
+
+#define GITS_SGIR_VPEID                        GENMASK_ULL(47, 32)
+#define GITS_SGIR_VINTID               GENMASK_ULL(3, 0)
+
 #define GITS_CTLR_ENABLE               (1U << 0)
 #define GITS_CTLR_ImDe                 (1U << 1)
 #define        GITS_CTLR_ITS_NUMBER_SHIFT      4
 #define GITS_CMD_VMAPTI                        GITS_CMD_GICv4(GITS_CMD_MAPTI)
 #define GITS_CMD_VMOVI                 GITS_CMD_GICv4(GITS_CMD_MOVI)
 #define GITS_CMD_VSYNC                 GITS_CMD_GICv4(GITS_CMD_SYNC)
-/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
+/* VMOVP, VSGI and INVDB are the odd ones, as they dont have a physical counterpart */
 #define GITS_CMD_VMOVP                 GITS_CMD_GICv4(2)
+#define GITS_CMD_VSGI                  GITS_CMD_GICv4(3)
 #define GITS_CMD_INVDB                 GITS_CMD_GICv4(0xe)
 
 /*
 
 struct rdists {
        struct {
+               raw_spinlock_t  rd_lock;
                void __iomem    *rd_base;
                struct page     *pend_page;
                phys_addr_t     phys_base;
index d9c34968467a56c1cdad0560d3156f152997040a..6976b8331b60439cc131033777412ccfdf2d31bc 100644 (file)
@@ -49,10 +49,22 @@ struct its_vpe {
                };
                /* GICv4.1 implementations */
                struct {
+                       struct fwnode_handle    *fwnode;
+                       struct irq_domain       *sgi_domain;
+                       struct {
+                               u8      priority;
+                               bool    enabled;
+                               bool    group;
+                       }                       sgi_config[16];
                        atomic_t vmapp_count;
                };
        };
 
+       /*
+        * Ensures mutual exclusion between affinity setting of the
+        * vPE and vLPI operations using vpe->col_idx.
+        */
+       raw_spinlock_t          vpe_lock;
        /*
         * This collection ID is used to indirect the target
         * redistributor for this VPE. The ID itself isn't involved in
@@ -93,6 +105,7 @@ enum its_vcpu_info_cmd_type {
        SCHEDULE_VPE,
        DESCHEDULE_VPE,
        INVALL_VPE,
+       PROP_UPDATE_VSGI,
 };
 
 struct its_cmd_info {
@@ -105,19 +118,27 @@ struct its_cmd_info {
                        bool            g0en;
                        bool            g1en;
                };
+               struct {
+                       u8              priority;
+                       bool            group;
+               };
        };
 };
 
 int its_alloc_vcpu_irqs(struct its_vm *vm);
 void its_free_vcpu_irqs(struct its_vm *vm);
-int its_schedule_vpe(struct its_vpe *vpe, bool on);
+int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en);
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db);
 int its_invall_vpe(struct its_vpe *vpe);
 int its_map_vlpi(int irq, struct its_vlpi_map *map);
 int its_get_vlpi(int irq, struct its_vlpi_map *map);
 int its_unmap_vlpi(int irq);
 int its_prop_update_vlpi(int irq, u8 config, bool inv);
+int its_prop_update_vsgi(int irq, u8 priority, bool group);
 
 struct irq_domain_ops;
-int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops);
+int its_init_v4(struct irq_domain *domain,
+               const struct irq_domain_ops *vpe_ops,
+               const struct irq_domain_ops *sgi_ops);
 
 #endif
index b2d47571ab676fcf81a301f1df091ad33f1eb7b6..8d062e86d954e11ef5fb46a8b00bb12287b6ad8b 100644 (file)
@@ -192,7 +192,7 @@ enum {
        IRQ_DOMAIN_FLAG_HIERARCHY       = (1 << 0),
 
        /* Irq domain name was allocated in __irq_domain_add() */
-       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 6),
+       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 1),
 
        /* Irq domain is an IPI domain with virq per cpu */
        IRQ_DOMAIN_FLAG_IPI_PER_CPU     = (1 << 2),
index b2bb44f87f5a3edb6ee6f179c83fcde42a363fe5..d1fb05135665b7df5add8c3b2cb2d690fade6b7e 100644 (file)
@@ -66,33 +66,15 @@ static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs)
  */
 #define ktime_sub_ns(kt, nsval)                ((kt) - (nsval))
 
-/* convert a timespec to ktime_t format: */
-static inline ktime_t timespec_to_ktime(struct timespec ts)
-{
-       return ktime_set(ts.tv_sec, ts.tv_nsec);
-}
-
 /* convert a timespec64 to ktime_t format: */
 static inline ktime_t timespec64_to_ktime(struct timespec64 ts)
 {
        return ktime_set(ts.tv_sec, ts.tv_nsec);
 }
 
-/* convert a timeval to ktime_t format: */
-static inline ktime_t timeval_to_ktime(struct timeval tv)
-{
-       return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
-}
-
-/* Map the ktime_t to timespec conversion to ns_to_timespec function */
-#define ktime_to_timespec(kt)          ns_to_timespec((kt))
-
 /* Map the ktime_t to timespec conversion to ns_to_timespec function */
 #define ktime_to_timespec64(kt)                ns_to_timespec64((kt))
 
-/* Map the ktime_t to timeval conversion to ns_to_timeval function */
-#define ktime_to_timeval(kt)           ns_to_timeval((kt))
-
 /* Convert ktime_t to nanoseconds */
 static inline s64 ktime_to_ns(const ktime_t kt)
 {
@@ -215,25 +197,6 @@ static inline ktime_t ktime_sub_ms(const ktime_t kt, const u64 msec)
 
 extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs);
 
-/**
- * ktime_to_timespec_cond - convert a ktime_t variable to timespec
- *                         format only if the variable contains data
- * @kt:                the ktime_t variable to convert
- * @ts:                the timespec variable to store the result in
- *
- * Return: %true if there was a successful conversion, %false if kt was 0.
- */
-static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt,
-                                                      struct timespec *ts)
-{
-       if (kt) {
-               *ts = ktime_to_timespec(kt);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * ktime_to_timespec64_cond - convert a ktime_t variable to timespec64
  *                         format only if the variable contains data
index 35bc52e187a23617bd20853c5164ef52d88b271c..f6a1905da9bfed8f6e7b5d6734f23d533b236186 100644 (file)
@@ -1032,6 +1032,9 @@ search_memslots(struct kvm_memslots *slots, gfn_t gfn)
        int slot = atomic_read(&slots->lru_slot);
        struct kvm_memory_slot *memslots = slots->memslots;
 
+       if (unlikely(!slots->used_slots))
+               return NULL;
+
        if (gfn >= memslots[slot].base_gfn &&
            gfn < memslots[slot].base_gfn + memslots[slot].npages)
                return &memslots[slot];
@@ -1350,7 +1353,7 @@ static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
 #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
 
 struct kvm_vcpu *kvm_get_running_vcpu(void);
-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 
 #ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
 bool kvm_arch_has_irq_bypass(void);
index ff8c9d527bb415d23d1fa6556a25e894145434b6..bfdf41537cf1facc8d24a2556e43df994c6832a4 100644 (file)
@@ -688,7 +688,10 @@ struct mlx5_ifc_flow_table_nic_cap_bits {
        u8         nic_rx_multi_path_tirs[0x1];
        u8         nic_rx_multi_path_tirs_fts[0x1];
        u8         allow_sniffer_and_nic_rx_shared_tir[0x1];
-       u8         reserved_at_3[0x1d];
+       u8         reserved_at_3[0x4];
+       u8         sw_owner_reformat_supported[0x1];
+       u8         reserved_at_8[0x18];
+
        u8         encap_general_header[0x1];
        u8         reserved_at_21[0xa];
        u8         log_max_packet_reformat_context[0x5];
index 9f1f633235f6b041d24109af61c9a6ad4b2aa374..6c3f7032e8d9d720aba0022662e72eccf6f1da2f 100644 (file)
@@ -72,6 +72,8 @@ void netdev_set_default_ethtool_ops(struct net_device *dev,
 #define NET_RX_SUCCESS         0       /* keep 'em coming, baby */
 #define NET_RX_DROP            1       /* packet dropped */
 
+#define MAX_NEST_DEV 8
+
 /*
  * Transmit return codes: transmit return codes originate from three different
  * namespaces:
@@ -4389,11 +4391,8 @@ void *netdev_lower_get_next(struct net_device *dev,
             ldev; \
             ldev = netdev_lower_get_next(dev, &(iter)))
 
-struct net_device *netdev_all_lower_get_next(struct net_device *dev,
+struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
                                             struct list_head **iter);
-struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
-                                                struct list_head **iter);
-
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *lower_dev,
                                        void *data),
index 908d38dbcb91f0b1e7040b230c2506fb3f67f14e..5448c8b443dbf52aeac423ee987d19bb63b23e76 100644 (file)
@@ -121,6 +121,7 @@ struct ip_set_ext {
        u32 timeout;
        u8 packets_op;
        u8 bytes_op;
+       bool target;
 };
 
 struct ip_set;
@@ -187,6 +188,14 @@ struct ip_set_type_variant {
        /* Return true if "b" set is the same as "a"
         * according to the create set parameters */
        bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
+       /* Region-locking is used */
+       bool region_lock;
+};
+
+struct ip_set_region {
+       spinlock_t lock;        /* Region lock */
+       size_t ext_size;        /* Size of the dynamic extensions */
+       u32 elements;           /* Number of elements vs timeout */
 };
 
 /* The core set type structure */
@@ -501,7 +510,7 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
 }
 
 #define IP_SET_INIT_KEXT(skb, opt, set)                        \
-       { .bytes = (skb)->len, .packets = 1,            \
+       { .bytes = (skb)->len, .packets = 1, .target = true,\
          .timeout = ip_set_adt_opt_timeout(opt, set) }
 
 #define IP_SET_INIT_UEXT(set)                          \
index e5b752027a031b119ce09a982b93f935c736c93d..9670b54b484a6f7849a15e458a7f63246f425b2b 100644 (file)
@@ -145,6 +145,13 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
        }
 }
 
+/* after that hlist_nulls_del will work */
+static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n)
+{
+       n->pprev = &n->next;
+       n->next = (struct hlist_nulls_node *)NULLS_MARKER(NULL);
+}
+
 /**
  * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type
  * @tpos:      the type * to use as a loop cursor.
index ca8806b693882e9ae933d70d0bb6c4cbd3ca81bd..5b50278c4bc852b7659f9af8e392a45630111d0b 100644 (file)
@@ -611,9 +611,15 @@ typedef unsigned char *sk_buff_data_t;
  *     @next: Next buffer in list
  *     @prev: Previous buffer in list
  *     @tstamp: Time we arrived/left
+ *     @skb_mstamp_ns: (aka @tstamp) earliest departure time; start point
+ *             for retransmit timer
  *     @rbnode: RB tree node, alternative to next/prev for netem/tcp
+ *     @list: queue head
  *     @sk: Socket we are owned by
+ *     @ip_defrag_offset: (aka @sk) alternate use of @sk, used in
+ *             fragmentation management
  *     @dev: Device we arrived on/are leaving by
+ *     @dev_scratch: (aka @dev) alternate use of @dev when @dev would be %NULL
  *     @cb: Control buffer. Free for use by every layer. Put private vars here
  *     @_skb_refdst: destination entry (with norefcount bit)
  *     @sp: the security path, used for xfrm
@@ -632,6 +638,9 @@ typedef unsigned char *sk_buff_data_t;
  *     @pkt_type: Packet class
  *     @fclone: skbuff clone status
  *     @ipvs_property: skbuff is owned by ipvs
+ *     @inner_protocol_type: whether the inner protocol is
+ *             ENCAP_TYPE_ETHER or ENCAP_TYPE_IPPROTO
+ *     @remcsum_offload: remote checksum offload is enabled
  *     @offload_fwd_mark: Packet was L2-forwarded in hardware
  *     @offload_l3_fwd_mark: Packet was L3-forwarded in hardware
  *     @tc_skip_classify: do not classify packet. set by IFB device
@@ -650,6 +659,8 @@ typedef unsigned char *sk_buff_data_t;
  *     @tc_index: Traffic control index
  *     @hash: the packet hash
  *     @queue_mapping: Queue mapping for multiqueue devices
+ *     @head_frag: skb was allocated from page fragments,
+ *             not allocated by kmalloc() or vmalloc().
  *     @pfmemalloc: skbuff was allocated from PFMEMALLOC reserves
  *     @active_extensions: active extensions (skb_ext_id types)
  *     @ndisc_nodetype: router type (from link layer)
@@ -660,15 +671,28 @@ typedef unsigned char *sk_buff_data_t;
  *     @wifi_acked_valid: wifi_acked was set
  *     @wifi_acked: whether frame was acked on wifi or not
  *     @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
+ *     @encapsulation: indicates the inner headers in the skbuff are valid
+ *     @encap_hdr_csum: software checksum is needed
+ *     @csum_valid: checksum is already valid
  *     @csum_not_inet: use CRC32c to resolve CHECKSUM_PARTIAL
+ *     @csum_complete_sw: checksum was completed by software
+ *     @csum_level: indicates the number of consecutive checksums found in
+ *             the packet minus one that have been verified as
+ *             CHECKSUM_UNNECESSARY (max 3)
  *     @dst_pending_confirm: need to confirm neighbour
  *     @decrypted: Decrypted SKB
  *     @napi_id: id of the NAPI struct this skb came from
+ *     @sender_cpu: (aka @napi_id) source CPU in XPS
  *     @secmark: security marking
  *     @mark: Generic packet mark
+ *     @reserved_tailroom: (aka @mark) number of bytes of free space available
+ *             at the tail of an sk_buff
+ *     @vlan_present: VLAN tag is present
  *     @vlan_proto: vlan encapsulation protocol
  *     @vlan_tci: vlan tag control information
  *     @inner_protocol: Protocol (encapsulation)
+ *     @inner_ipproto: (aka @inner_protocol) stores ipproto when
+ *             skb->inner_protocol_type == ENCAP_TYPE_IPPROTO;
  *     @inner_transport_header: Inner transport layer header (encapsulation)
  *     @inner_network_header: Network layer header (encapsulation)
  *     @inner_mac_header: Link layer header (encapsulation)
@@ -750,7 +774,9 @@ struct sk_buff {
 #endif
 #define CLONED_OFFSET()                offsetof(struct sk_buff, __cloned_offset)
 
+       /* private: */
        __u8                    __cloned_offset[0];
+       /* public: */
        __u8                    cloned:1,
                                nohdr:1,
                                fclone:2,
@@ -775,7 +801,9 @@ struct sk_buff {
 #endif
 #define PKT_TYPE_OFFSET()      offsetof(struct sk_buff, __pkt_type_offset)
 
+       /* private: */
        __u8                    __pkt_type_offset[0];
+       /* public: */
        __u8                    pkt_type:3;
        __u8                    ignore_df:1;
        __u8                    nf_trace:1;
@@ -798,7 +826,9 @@ struct sk_buff {
 #define PKT_VLAN_PRESENT_BIT   0
 #endif
 #define PKT_VLAN_PRESENT_OFFSET()      offsetof(struct sk_buff, __pkt_vlan_present_offset)
+       /* private: */
        __u8                    __pkt_vlan_present_offset[0];
+       /* public: */
        __u8                    vlan_present:1;
        __u8                    csum_complete_sw:1;
        __u8                    csum_level:2;
index cde3dc18e21a2cdee5ef36183d180946e45be0ea..046bb94bd4d61da998a809a82eebdc22691c0ee7 100644 (file)
@@ -64,6 +64,9 @@ extern void swiotlb_tbl_sync_single(struct device *hwdev,
                                    size_t size, enum dma_data_direction dir,
                                    enum dma_sync_target target);
 
+dma_addr_t swiotlb_map(struct device *dev, phys_addr_t phys,
+               size_t size, enum dma_data_direction dir, unsigned long attrs);
+
 #ifdef CONFIG_SWIOTLB
 extern enum swiotlb_force swiotlb_force;
 extern phys_addr_t io_tlb_start, io_tlb_end;
@@ -73,8 +76,6 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
        return paddr >= io_tlb_start && paddr < io_tlb_end;
 }
 
-bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
-               size_t size, enum dma_data_direction dir, unsigned long attrs);
 void __init swiotlb_exit(void);
 unsigned int swiotlb_max_segment(void);
 size_t swiotlb_max_mapping_size(struct device *dev);
@@ -85,12 +86,6 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
 {
        return false;
 }
-static inline bool swiotlb_map(struct device *dev, phys_addr_t *phys,
-               dma_addr_t *dma_addr, size_t size, enum dma_data_direction dir,
-               unsigned long attrs)
-{
-       return false;
-}
 static inline void swiotlb_exit(void)
 {
 }
index cad4c318600213430212947cbec7a63859654f3c..cf9320cd2d0bda2ab247e234dbdd53a778eeec24 100644 (file)
@@ -12,8 +12,6 @@
 #include <linux/time64.h>
 #include <linux/timex.h>
 
-#define TIME_T_MAX     (__kernel_old_time_t)((1UL << ((sizeof(__kernel_old_time_t) << 3) - 1)) - 1)
-
 typedef s32            old_time32_t;
 
 struct old_timespec32 {
@@ -73,162 +71,12 @@ struct __kernel_timex;
 int get_old_timex32(struct __kernel_timex *, const struct old_timex32 __user *);
 int put_old_timex32(struct old_timex32 __user *, const struct __kernel_timex *);
 
-#if __BITS_PER_LONG == 64
-
-/* timespec64 is defined as timespec here */
-static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
-{
-       return *(const struct timespec *)&ts64;
-}
-
-static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
-{
-       return *(const struct timespec64 *)&ts;
-}
-
-#else
-static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
-{
-       struct timespec ret;
-
-       ret.tv_sec = (time_t)ts64.tv_sec;
-       ret.tv_nsec = ts64.tv_nsec;
-       return ret;
-}
-
-static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
-{
-       struct timespec64 ret;
-
-       ret.tv_sec = ts.tv_sec;
-       ret.tv_nsec = ts.tv_nsec;
-       return ret;
-}
-#endif
-
-static inline int timespec_equal(const struct timespec *a,
-                                const struct timespec *b)
-{
-       return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
-}
-
-/*
- * lhs < rhs:  return <0
- * lhs == rhs: return 0
- * lhs > rhs:  return >0
- */
-static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_nsec - rhs->tv_nsec;
-}
-
-/*
- * Returns true if the timespec is norm, false if denorm:
- */
-static inline bool timespec_valid(const struct timespec *ts)
-{
-       /* Dates before 1970 are bogus */
-       if (ts->tv_sec < 0)
-               return false;
-       /* Can't have more nanoseconds then a second */
-       if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
-               return false;
-       return true;
-}
-
-/**
- * timespec_to_ns - Convert timespec to nanoseconds
- * @ts:                pointer to the timespec variable to be converted
- *
- * Returns the scalar nanosecond representation of the timespec
- * parameter.
- */
-static inline s64 timespec_to_ns(const struct timespec *ts)
-{
-       return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
-}
-
 /**
- * ns_to_timespec - Convert nanoseconds to timespec
- * @nsec:      the nanoseconds value to be converted
- *
- * Returns the timespec representation of the nsec parameter.
- */
-extern struct timespec ns_to_timespec(const s64 nsec);
-
-/**
- * timespec_add_ns - Adds nanoseconds to a timespec
- * @a:         pointer to timespec to be incremented
- * @ns:                unsigned nanoseconds value to be added
- *
- * This must always be inlined because its used from the x86-64 vdso,
- * which cannot call other kernel functions.
- */
-static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
-{
-       a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
-       a->tv_nsec = ns;
-}
-
-static inline unsigned long mktime(const unsigned int year,
-                       const unsigned int mon, const unsigned int day,
-                       const unsigned int hour, const unsigned int min,
-                       const unsigned int sec)
-{
-       return mktime64(year, mon, day, hour, min, sec);
-}
-
-static inline bool timeval_valid(const struct timeval *tv)
-{
-       /* Dates before 1970 are bogus */
-       if (tv->tv_sec < 0)
-               return false;
-
-       /* Can't have more microseconds then a second */
-       if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
-               return false;
-
-       return true;
-}
-
-/**
- * timeval_to_ns - Convert timeval to nanoseconds
- * @ts:                pointer to the timeval variable to be converted
- *
- * Returns the scalar nanosecond representation of the timeval
- * parameter.
- */
-static inline s64 timeval_to_ns(const struct timeval *tv)
-{
-       return ((s64) tv->tv_sec * NSEC_PER_SEC) +
-               tv->tv_usec * NSEC_PER_USEC;
-}
-
-/**
- * ns_to_timeval - Convert nanoseconds to timeval
+ * ns_to_kernel_old_timeval - Convert nanoseconds to timeval
  * @nsec:      the nanoseconds value to be converted
  *
  * Returns the timeval representation of the nsec parameter.
  */
-extern struct timeval ns_to_timeval(const s64 nsec);
 extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec);
 
-/*
- * Old names for the 32-bit time_t interfaces, these will be removed
- * when everything uses the new names.
- */
-#define compat_time_t          old_time32_t
-#define compat_timeval         old_timeval32
-#define compat_timespec                old_timespec32
-#define compat_itimerspec      old_itimerspec32
-#define ns_to_compat_timeval   ns_to_old_timeval32
-#define get_compat_itimerspec64        get_old_itimerspec32
-#define put_compat_itimerspec64        put_old_itimerspec32
-#define compat_get_timespec64  get_old_timespec32
-#define compat_put_timespec64  put_old_timespec32
-
 #endif
index cc59cc9e0e841dc8980882837afb03a5ae10a51e..266017fc9ee9c194bd5013161a442007e23cd9cf 100644 (file)
@@ -11,36 +11,4 @@ static inline unsigned long get_seconds(void)
        return ktime_get_real_seconds();
 }
 
-static inline void getnstimeofday(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_real_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void ktime_get_ts(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void getrawmonotonic(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_raw_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void getboottime(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       getboottime64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
 #endif
index bfa4e2ee94a9de340321ecdd4141272643ca9115..bd5fe0e907e8c1c219a496120d49a0fa42b8c736 100644 (file)
@@ -225,6 +225,8 @@ struct tty_port_client_operations {
        void (*write_wakeup)(struct tty_port *port);
 };
 
+extern const struct tty_port_client_operations tty_port_default_client_ops;
+
 struct tty_port {
        struct tty_bufhead      buf;            /* Locked internally */
        struct tty_struct       *tty;           /* Back pointer */
index eb870ad42919de7fb1e6a41ded184460b0cb0b81..d3021c87917953be758958fdf0fef4731702224c 100644 (file)
@@ -65,11 +65,6 @@ typedef __kernel_ssize_t     ssize_t;
 typedef __kernel_ptrdiff_t     ptrdiff_t;
 #endif
 
-#ifndef _TIME_T
-#define _TIME_T
-typedef __kernel_old_time_t    time_t;
-#endif
-
 #ifndef _CLOCK_T
 #define _CLOCK_T
 typedef __kernel_clock_t       clock_t;
index a1be64c9940fb4ad4e2365f226419f050d6addba..22c1f579afe3020b22ed36a40523ab34c08a3292 100644 (file)
@@ -69,4 +69,7 @@
 /* Hub needs extra delay after resetting its port. */
 #define USB_QUIRK_HUB_SLOW_RESET               BIT(14)
 
+/* device has blacklisted endpoints */
+#define USB_QUIRK_ENDPOINT_BLACKLIST           BIT(15)
+
 #endif /* __LINUX_USB_QUIRKS_H */
index e9391e877f9a11d630eb95f0fb4924b967c4cbd7..62838391582760a6e4101a2c9dde0b3dd9922218 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/in6.h>
 #include <linux/siphash.h>
+#include <linux/string.h>
 #include <uapi/linux/if_ether.h>
 
 struct sk_buff;
@@ -348,4 +349,12 @@ struct bpf_flow_dissector {
        void                    *data_end;
 };
 
+static inline void
+flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
+                        struct flow_dissector_key_basic *key_basic)
+{
+       memset(key_control, 0, sizeof(*key_control));
+       memset(key_basic, 0, sizeof(*key_basic));
+}
+
 #endif
index 02162b0378f73f9221aec78e7adedd7124ef652b..328564525526914f9d7aed9216a2fd5f8c255af4 100644 (file)
@@ -117,19 +117,26 @@ typedef __u64 __bitwise __addrpair;
  *     struct sock_common - minimal network layer representation of sockets
  *     @skc_daddr: Foreign IPv4 addr
  *     @skc_rcv_saddr: Bound local IPv4 addr
+ *     @skc_addrpair: 8-byte-aligned __u64 union of @skc_daddr & @skc_rcv_saddr
  *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_u16hashes: two u16 hash values used by UDP lookup tables
  *     @skc_dport: placeholder for inet_dport/tw_dport
  *     @skc_num: placeholder for inet_num/tw_num
+ *     @skc_portpair: __u32 union of @skc_dport & @skc_num
  *     @skc_family: network address family
  *     @skc_state: Connection state
  *     @skc_reuse: %SO_REUSEADDR setting
  *     @skc_reuseport: %SO_REUSEPORT setting
+ *     @skc_ipv6only: socket is IPV6 only
+ *     @skc_net_refcnt: socket is using net ref counting
  *     @skc_bound_dev_if: bound device index if != 0
  *     @skc_bind_node: bind hash linkage for various protocol lookup tables
  *     @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol
  *     @skc_prot: protocol handlers inside a network family
  *     @skc_net: reference to the network namespace of this socket
+ *     @skc_v6_daddr: IPV6 destination address
+ *     @skc_v6_rcv_saddr: IPV6 source address
+ *     @skc_cookie: socket's cookie value
  *     @skc_node: main hash linkage for various protocol lookup tables
  *     @skc_nulls_node: main hash linkage for TCP/UDP/UDP-Lite protocol
  *     @skc_tx_queue_mapping: tx queue number for this connection
@@ -137,7 +144,15 @@ typedef __u64 __bitwise __addrpair;
  *     @skc_flags: place holder for sk_flags
  *             %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
  *             %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
+ *     @skc_listener: connection request listener socket (aka rsk_listener)
+ *             [union with @skc_flags]
+ *     @skc_tw_dr: (aka tw_dr) ptr to &struct inet_timewait_death_row
+ *             [union with @skc_flags]
  *     @skc_incoming_cpu: record/match cpu processing incoming packets
+ *     @skc_rcv_wnd: (aka rsk_rcv_wnd) TCP receive window size (possibly scaled)
+ *             [union with @skc_incoming_cpu]
+ *     @skc_tw_rcv_nxt: (aka tw_rcv_nxt) TCP window next expected seq number
+ *             [union with @skc_incoming_cpu]
  *     @skc_refcnt: reference count
  *
  *     This is the minimal network layer representation of sockets, the header
@@ -245,6 +260,7 @@ struct bpf_sk_storage;
   *    @sk_dst_cache: destination cache
   *    @sk_dst_pending_confirm: need to confirm neighbour
   *    @sk_policy: flow policy
+  *    @sk_rx_skb_cache: cache copy of recently accessed RX skb
   *    @sk_receive_queue: incoming packets
   *    @sk_wmem_alloc: transmit queue bytes committed
   *    @sk_tsq_flags: TCP Small Queues flags
@@ -265,6 +281,8 @@ struct bpf_sk_storage;
   *    @sk_no_check_rx: allow zero checksum in RX packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *    @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
+  *    @sk_route_forced_caps: static, forced route capabilities
+  *            (set in tcp_init_sock())
   *    @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
   *    @sk_gso_max_size: Maximum GSO segment size to build
   *    @sk_gso_max_segs: Maximum number of GSO segments
@@ -303,6 +321,8 @@ struct bpf_sk_storage;
   *    @sk_frag: cached page frag
   *    @sk_peek_off: current peek_offset value
   *    @sk_send_head: front of stuff to transmit
+  *    @tcp_rtx_queue: TCP re-transmit queue [union with @sk_send_head]
+  *    @sk_tx_skb_cache: cache copy of recently accessed TX skb
   *    @sk_security: used by security modules
   *    @sk_mark: generic packet mark
   *    @sk_cgrp_data: cgroup data for this cgroup
@@ -313,11 +333,14 @@ struct bpf_sk_storage;
   *    @sk_write_space: callback to indicate there is bf sending space available
   *    @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
   *    @sk_backlog_rcv: callback to process the backlog
+  *    @sk_validate_xmit_skb: ptr to an optional validate function
   *    @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
   *    @sk_reuseport_cb: reuseport group container
+  *    @sk_bpf_storage: ptr to cache and control for bpf_sk_storage
   *    @sk_rcu: used during RCU grace period
   *    @sk_clockid: clockid used by time-based scheduling (SO_TXTIME)
   *    @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME
+  *    @sk_txtime_report_errors: set report errors mode for SO_TXTIME
   *    @sk_txtime_unused: unused txtime flags
   */
 struct sock {
@@ -393,7 +416,9 @@ struct sock {
        struct sk_filter __rcu  *sk_filter;
        union {
                struct socket_wq __rcu  *sk_wq;
+               /* private: */
                struct socket_wq        *sk_wq_raw;
+               /* public: */
        };
 #ifdef CONFIG_XFRM
        struct xfrm_policy __rcu *sk_policy[2];
@@ -2017,7 +2042,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro
  * sk_wmem_alloc_get - returns write allocations
  * @sk: socket
  *
- * Returns sk_wmem_alloc minus initial offset of one
+ * Return: sk_wmem_alloc minus initial offset of one
  */
 static inline int sk_wmem_alloc_get(const struct sock *sk)
 {
@@ -2028,7 +2053,7 @@ static inline int sk_wmem_alloc_get(const struct sock *sk)
  * sk_rmem_alloc_get - returns read allocations
  * @sk: socket
  *
- * Returns sk_rmem_alloc
+ * Return: sk_rmem_alloc
  */
 static inline int sk_rmem_alloc_get(const struct sock *sk)
 {
@@ -2039,7 +2064,7 @@ static inline int sk_rmem_alloc_get(const struct sock *sk)
  * sk_has_allocations - check if allocations are outstanding
  * @sk: socket
  *
- * Returns true if socket has write or read allocations
+ * Return: true if socket has write or read allocations
  */
 static inline bool sk_has_allocations(const struct sock *sk)
 {
@@ -2050,7 +2075,7 @@ static inline bool sk_has_allocations(const struct sock *sk)
  * skwq_has_sleeper - check if there are any waiting processes
  * @wq: struct socket_wq
  *
- * Returns true if socket_wq has waiting processes
+ * Return: true if socket_wq has waiting processes
  *
  * The purpose of the skwq_has_sleeper and sock_poll_wait is to wrap the memory
  * barrier call. They were added due to the race found within the tcp code.
@@ -2238,6 +2263,9 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
  * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest
  * inside other socket operations and end up recursing into sk_page_frag()
  * while it's already in use.
+ *
+ * Return: a per task page_frag if context allows that,
+ * otherwise a per socket one.
  */
 static inline struct page_frag *sk_page_frag(struct sock *sk)
 {
@@ -2432,6 +2460,7 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
                           &skb_shinfo(skb)->tskey);
 }
 
+DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
 /**
  * sk_eat_skb - Release a skb if it is no longer needed
  * @sk: socket to eat this skb from
@@ -2440,7 +2469,6 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
 */
-DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
 static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
 {
        __skb_unlink(skb, &sk->sk_receive_queue);
index 533f56733ba84053e1ecb6f30d2fa344b900dda2..b71b5c4f418c5e5e5460bcbcbdb9742226ce70c3 100644 (file)
@@ -627,7 +627,6 @@ struct iscsi_reject {
 #define ISCSI_REASON_BOOKMARK_INVALID  9
 #define ISCSI_REASON_BOOKMARK_NO_RESOURCES     10
 #define ISCSI_REASON_NEGOTIATION_RESET 11
-#define ISCSI_REASON_WAITING_FOR_LOGOUT        12
 
 /* Max. number of Key=Value pairs in a text message */
 #define MAX_KEY_VALUE_PAIRS    8192
index 40ab20439fee21d650fdb9d72beb817ceb4b71aa..a36b7227a15ad5dee698a60d3c15d5fae63c04ee 100644 (file)
@@ -77,9 +77,9 @@ struct snd_rawmidi_substream {
        struct list_head list;          /* list of all substream for given stream */
        int stream;                     /* direction */
        int number;                     /* substream number */
-       unsigned int opened: 1,         /* open flag */
-                    append: 1,         /* append flag (merge more streams) */
-                    active_sensing: 1; /* send active sensing when close */
+       bool opened;                    /* open flag */
+       bool append;                    /* append flag (merge more streams) */
+       bool active_sensing;            /* send active sensing when close */
        int use_count;                  /* use counter (for output) */
        size_t bytes;
        struct snd_rawmidi *rmidi;
index 2a306c6f3fbcb7595302d9a30f70d9f62a05ca65..1b6afbc1a4ed10676c0bc188b1065d1936c2427c 100644 (file)
@@ -392,8 +392,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
index 2f9c80595ba771e41767beb5d814b3204a39d332..b5f7594eee7ab26ced0d3041ffa04a2662a39818 100644 (file)
@@ -87,7 +87,9 @@ typedef struct {
 typedef __kernel_long_t        __kernel_off_t;
 typedef long long      __kernel_loff_t;
 typedef __kernel_long_t        __kernel_old_time_t;
+#ifndef __KERNEL__
 typedef __kernel_long_t        __kernel_time_t;
+#endif
 typedef long long __kernel_time64_t;
 typedef __kernel_long_t        __kernel_clock_t;
 typedef int            __kernel_timer_t;
index f1d74a2bd23493635afcbd6a7336c2fd2806f471..22f235260a3a352cf4223249fc1d26f2fce62f34 100644 (file)
@@ -1045,9 +1045,9 @@ union bpf_attr {
  *             supports redirection to the egress interface, and accepts no
  *             flag at all.
  *
- *             The same effect can be attained with the more generic
- *             **bpf_redirect_map**\ (), which requires specific maps to be
- *             used but offers better performance.
+ *             The same effect can also be attained with the more generic
+ *             **bpf_redirect_map**\ (), which uses a BPF map to store the
+ *             redirect target instead of providing it directly to the helper.
  *     Return
  *             For XDP, the helper returns **XDP_REDIRECT** on success or
  *             **XDP_ABORTED** on error. For other program types, the values
@@ -1611,13 +1611,11 @@ union bpf_attr {
  *             the caller. Any higher bits in the *flags* argument must be
  *             unset.
  *
- *             When used to redirect packets to net devices, this helper
- *             provides a high performance increase over **bpf_redirect**\ ().
- *             This is due to various implementation details of the underlying
- *             mechanisms, one of which is the fact that **bpf_redirect_map**\
- *             () tries to send packet as a "bulk" to the device.
+ *             See also bpf_redirect(), which only supports redirecting to an
+ *             ifindex, but doesn't require a map to do so.
  *     Return
- *             **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
+ *             **XDP_REDIRECT** on success, or the value of the two lower bits
+ *             of the **flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 336014bf8868c3f04b92cdbf31bdf2ccafc68a71..b6f0bb1dc7998e67add1a97a62b69a07f68147e2 100644 (file)
@@ -97,6 +97,15 @@ enum ip_conntrack_status {
        IPS_UNTRACKED_BIT = 12,
        IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
 
+#ifdef __KERNEL__
+       /* Re-purposed for in-kernel use:
+        * Tags a conntrack entry that clashed with an existing entry
+        * on insert.
+        */
+       IPS_NAT_CLASH_BIT = IPS_UNTRACKED_BIT,
+       IPS_NAT_CLASH = IPS_UNTRACKED,
+#endif
+
        /* Conntrack got a helper explicitly attached via CT target. */
        IPS_HELPER_BIT = 13,
        IPS_HELPER = (1 << IPS_HELPER_BIT),
@@ -110,7 +119,8 @@ enum ip_conntrack_status {
         */
        IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
                                 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
-                                IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
+                                IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED |
+                                IPS_OFFLOAD),
 
        __IPS_MAX_BIT = 15,
 };
index fa7f97da5b7687125c5ca5eb1527419639a1b8e8..7272f85d6d6ab5e24dd806e7f88760eaafcd7326 100644 (file)
@@ -135,9 +135,9 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val)
 
 static __always_inline unsigned long __swab(const unsigned long y)
 {
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
        return __swab64(y);
-#else /* BITS_PER_LONG == 32 */
+#else /* __BITS_PER_LONG == 32 */
        return __swab32(y);
 #endif
 }
index a655aa28dc6efcbf0da9a845bc1cbd09e47545e3..4f4b6e48e01c426560483c6c4277228334cbfddf 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/time_types.h>
 
+#ifndef __KERNEL__
 #ifndef _STRUCT_TIMESPEC
 #define _STRUCT_TIMESPEC
 struct timespec {
@@ -18,6 +19,17 @@ struct timeval {
        __kernel_suseconds_t    tv_usec;        /* microseconds */
 };
 
+struct itimerspec {
+       struct timespec it_interval;/* timer period */
+       struct timespec it_value;       /* timer expiration */
+};
+
+struct itimerval {
+       struct timeval it_interval;/* timer interval */
+       struct timeval it_value;        /* current value */
+};
+#endif
+
 struct timezone {
        int     tz_minuteswest; /* minutes west of Greenwich */
        int     tz_dsttime;     /* type of dst correction */
@@ -31,16 +43,6 @@ struct timezone {
 #define        ITIMER_VIRTUAL          1
 #define        ITIMER_PROF             2
 
-struct itimerspec {
-       struct timespec it_interval;    /* timer period */
-       struct timespec it_value;       /* timer expiration */
-};
-
-struct itimerval {
-       struct timeval it_interval;     /* timer interval */
-       struct timeval it_value;        /* current value */
-};
-
 /*
  * The IDs of the various system clocks (for POSIX.1b interval timers):
  */
index 5f72af35b3ed768fd3bc1e2d8ca3f4f6ecaea47f..ad22079125bff2ba34f03b74e6cfd5e2eb460479 100644 (file)
  * ACA (Accessory Charger Adapters)
  */
 enum usb_charger_type {
-       UNKNOWN_TYPE,
-       SDP_TYPE,
-       DCP_TYPE,
-       CDP_TYPE,
-       ACA_TYPE,
+       UNKNOWN_TYPE = 0,
+       SDP_TYPE = 1,
+       DCP_TYPE = 2,
+       CDP_TYPE = 3,
+       ACA_TYPE = 4,
 };
 
 /* USB charger state */
 enum usb_charger_state {
-       USB_CHARGER_DEFAULT,
-       USB_CHARGER_PRESENT,
-       USB_CHARGER_ABSENT,
+       USB_CHARGER_DEFAULT = 0,
+       USB_CHARGER_PRESENT = 1,
+       USB_CHARGER_ABSENT = 2,
 };
 
 #endif /* _UAPI__LINUX_USB_CHARGER_H */
index 452bc1835cd4d91339ad187f9f935b636d3a94e9..20a6ac33761c98a6bb7466d5ec1a5e476b1eddda 100644 (file)
@@ -1226,13 +1226,12 @@ endif
 
 config BOOT_CONFIG
        bool "Boot config support"
-       depends on BLK_DEV_INITRD
-       default y
+       select BLK_DEV_INITRD
        help
          Extra boot config allows system admin to pass a config file as
          complemental extension of kernel cmdline when booting.
          The boot config file must be attached at the end of initramfs
-         with checksum and size.
+         with checksum, size and magic word.
          See <file:Documentation/admin-guide/bootconfig.rst> for details.
 
          If unsure, say Y.
index f95b014a5479712176e385174cb81ff51e1b65df..ee4947af823f3bb81ce5502781d24c4de6d3eb7f 100644 (file)
@@ -268,7 +268,6 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
 {
        struct xbc_node *knode, *vnode;
        char *end = buf + size;
-       char c = '\"';
        const char *val;
        int ret;
 
@@ -279,25 +278,20 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
                        return ret;
 
                vnode = xbc_node_get_child(knode);
-               ret = snprintf(buf, rest(buf, end), "%s%c", xbc_namebuf,
-                               vnode ? '=' : ' ');
-               if (ret < 0)
-                       return ret;
-               buf += ret;
-               if (!vnode)
+               if (!vnode) {
+                       ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+                       if (ret < 0)
+                               return ret;
+                       buf += ret;
                        continue;
-
-               c = '\"';
+               }
                xbc_array_for_each_value(vnode, val) {
-                       ret = snprintf(buf, rest(buf, end), "%c%s", c, val);
+                       ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ",
+                                      xbc_namebuf, val);
                        if (ret < 0)
                                return ret;
                        buf += ret;
-                       c = ',';
                }
-               if (rest(buf, end) > 2)
-                       strcpy(buf, "\" ");
-               buf += 2;
        }
 
        return buf - (end - size);
@@ -335,7 +329,7 @@ static char * __init xbc_make_cmdline(const char *key)
        return new_cmdline;
 }
 
-u32 boot_config_checksum(unsigned char *p, u32 size)
+static u32 boot_config_checksum(unsigned char *p, u32 size)
 {
        u32 ret = 0;
 
@@ -374,7 +368,11 @@ static void __init setup_boot_config(const char *cmdline)
        if (!initrd_end)
                goto not_found;
 
-       hdr = (u32 *)(initrd_end - 8);
+       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
+       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+               goto not_found;
+
+       hdr = (u32 *)(data - 8);
        size = hdr[0];
        csum = hdr[1];
 
@@ -418,6 +416,14 @@ not_found:
 }
 #else
 #define setup_boot_config(cmdline)     do { } while (0)
+
+static int __init warn_bootconfig(char *str)
+{
+       pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOTCONFIG is not set.\n");
+       return 0;
+}
+early_param("bootconfig", warn_bootconfig);
+
 #endif
 
 /* Change NUL term back to "=", to make "param" the whole string. */
index 4f4303f320776cfb0b7f8de192d9f43e72a34087..3687b71151b3921860613dcc7089fa2831f6237e 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -2384,11 +2384,9 @@ void exit_sem(struct task_struct *tsk)
                ipc_assert_locked_object(&sma->sem_perm);
                list_del(&un->list_id);
 
-               /* we are the last process using this ulp, acquiring ulp->lock
-                * isn't required. Besides that, we are also protected against
-                * IPC_RMID as we hold sma->sem_perm lock now
-                */
+               spin_lock(&ulp->lock);
                list_del_rcu(&un->list_proc);
+               spin_unlock(&ulp->lock);
 
                /* perform adjustments registered in un */
                for (i = 0; i < sma->sem_nsems; i++) {
index 17b0d523afb35cea50ee0ea8c5063c08b4cd209e..9ddfe2aa6671ff3d6558ee86c97cb64c5a9b3189 100644 (file)
@@ -1101,13 +1101,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
        audit_log_end(ab);
 }
 
-static int audit_set_feature(struct sk_buff *skb)
+static int audit_set_feature(struct audit_features *uaf)
 {
-       struct audit_features *uaf;
        int i;
 
        BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names));
-       uaf = nlmsg_data(nlmsg_hdr(skb));
 
        /* if there is ever a version 2 we should handle that here */
 
@@ -1175,6 +1173,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        u32                     seq;
        void                    *data;
+       int                     data_len;
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
@@ -1188,6 +1187,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
+       data_len = nlmsg_len(nlh);
 
        switch (msg_type) {
        case AUDIT_GET: {
@@ -1211,7 +1211,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct audit_status     s;
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                if (s.mask & AUDIT_STATUS_ENABLED) {
                        err = audit_set_enabled(s.enabled);
                        if (err < 0)
@@ -1315,7 +1315,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return err;
                break;
        case AUDIT_SET_FEATURE:
-               err = audit_set_feature(skb);
+               if (data_len < sizeof(struct audit_features))
+                       return -EINVAL;
+               err = audit_set_feature(data);
                if (err)
                        return err;
                break;
@@ -1327,6 +1329,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
+                       char *str = data;
+
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
                                err = tty_audit_push();
@@ -1334,26 +1338,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                        break;
                        }
                        audit_log_user_recv_msg(&ab, msg_type);
-                       if (msg_type != AUDIT_USER_TTY)
+                       if (msg_type != AUDIT_USER_TTY) {
+                               /* ensure NULL termination */
+                               str[data_len - 1] = '\0';
                                audit_log_format(ab, " msg='%.*s'",
                                                 AUDIT_MESSAGE_TEXT_MAX,
-                                                (char *)data);
-                       else {
-                               int size;
-
+                                                str);
+                       } else {
                                audit_log_format(ab, " data=");
-                               size = nlmsg_len(nlh);
-                               if (size > 0 &&
-                                   ((unsigned char *)data)[size - 1] == '\0')
-                                       size--;
-                               audit_log_n_untrustedstring(ab, data, size);
+                               if (data_len > 0 && str[data_len - 1] == '\0')
+                                       data_len--;
+                               audit_log_n_untrustedstring(ab, str, data_len);
                        }
                        audit_log_end(ab);
                }
                break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
-               if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
+               if (data_len < sizeof(struct audit_rule_data))
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
                        audit_log_common_recv_msg(audit_context(), &ab,
@@ -1365,7 +1367,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        audit_log_end(ab);
                        return -EPERM;
                }
-               err = audit_rule_change(msg_type, seq, data, nlmsg_len(nlh));
+               err = audit_rule_change(msg_type, seq, data, data_len);
                break;
        case AUDIT_LIST_RULES:
                err = audit_list_rules_send(skb, seq);
@@ -1380,7 +1382,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_MAKE_EQUIV: {
                void *bufp = data;
                u32 sizes[2];
-               size_t msglen = nlmsg_len(nlh);
+               size_t msglen = data_len;
                char *old, *new;
 
                err = -EINVAL;
@@ -1456,7 +1458,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                /* check if new data is valid */
                if ((s.enabled != 0 && s.enabled != 1) ||
                    (s.log_passwd != 0 && s.log_passwd != 1))
index b0126e9c0743e8d8adf07bc12404c852b2eab29b..026e34da4ace994e75408990b564d52e25352eea 100644 (file)
@@ -456,6 +456,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
        bufp = data->buf;
        for (i = 0; i < data->field_count; i++) {
                struct audit_field *f = &entry->rule.fields[i];
+               u32 f_val;
 
                err = -EINVAL;
 
@@ -464,12 +465,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        goto exit_free;
 
                f->type = data->fields[i];
-               f->val = data->values[i];
+               f_val = data->values[i];
 
                /* Support legacy tests for a valid loginuid */
-               if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
+               if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) {
                        f->type = AUDIT_LOGINUID_SET;
-                       f->val = 0;
+                       f_val = 0;
                        entry->rule.pflags |= AUDIT_LOGINUID_LEGACY;
                }
 
@@ -485,7 +486,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_OBJ_UID:
-                       f->uid = make_kuid(current_user_ns(), f->val);
+                       f->uid = make_kuid(current_user_ns(), f_val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
                        break;
@@ -494,11 +495,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       f->gid = make_kgid(current_user_ns(), f->val);
+                       f->gid = make_kgid(current_user_ns(), f_val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
                case AUDIT_ARCH:
+                       f->val = f_val;
                        entry->rule.arch_f = f;
                        break;
                case AUDIT_SUBJ_USER:
@@ -511,11 +513,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_OBJ_TYPE:
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
+                       entry->rule.buflen += f_val;
+                       f->lsm_str = str;
                        err = security_audit_rule_init(f->type, f->op, str,
                                                       (void **)&f->lsm_rule);
                        /* Keep currently invalid fields around in case they
@@ -524,68 +528,71 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                pr_warn("audit rule for LSM \'%s\' is invalid\n",
                                        str);
                                err = 0;
-                       }
-                       if (err) {
-                               kfree(str);
+                       } else if (err)
                                goto exit_free;
-                       } else
-                               f->lsm_str = str;
                        break;
                case AUDIT_WATCH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
-                       err = audit_to_watch(&entry->rule, str, f->val, f->op);
+                       }
+                       err = audit_to_watch(&entry->rule, str, f_val, f->op);
                        if (err) {
                                kfree(str);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_DIR:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
                        err = audit_make_tree(&entry->rule, str, f->op);
                        kfree(str);
                        if (err)
                                goto exit_free;
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_INODE:
+                       f->val = f_val;
                        err = audit_to_inode(&entry->rule, f);
                        if (err)
                                goto exit_free;
                        break;
                case AUDIT_FILTERKEY:
-                       if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
+                       if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
+                       }
+                       entry->rule.buflen += f_val;
                        entry->rule.filterkey = str;
                        break;
                case AUDIT_EXE:
-                       if (entry->rule.exe || f->val > PATH_MAX)
+                       if (entry->rule.exe || f_val > PATH_MAX)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
+                       str = audit_unpack_string(&bufp, &remain, f_val);
                        if (IS_ERR(str)) {
                                err = PTR_ERR(str);
                                goto exit_free;
                        }
-                       entry->rule.buflen += f->val;
-
-                       audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
+                       audit_mark = audit_alloc_mark(&entry->rule, str, f_val);
                        if (IS_ERR(audit_mark)) {
                                kfree(str);
                                err = PTR_ERR(audit_mark);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        entry->rule.exe = audit_mark;
                        break;
+               default:
+                       f->val = f_val;
+                       break;
                }
        }
 
index 805c43b083e956940b990cede2b3cad0f0e3692a..787140095e58d5d0882a50b32ad30d64dcb89a75 100644 (file)
@@ -4142,9 +4142,9 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
  * EFAULT - verifier bug
  * 0 - 99% match. The last 1% is validated by the verifier.
  */
-int btf_check_func_type_match(struct bpf_verifier_log *log,
-                             struct btf *btf1, const struct btf_type *t1,
-                             struct btf *btf2, const struct btf_type *t2)
+static int btf_check_func_type_match(struct bpf_verifier_log *log,
+                                    struct btf *btf1, const struct btf_type *t1,
+                                    struct btf *btf2, const struct btf_type *t2)
 {
        const struct btf_param *args1, *args2;
        const char *fn1, *fn2, *s1, *s2;
index 2d182c4ee9d9964a6ec55ea102a5de9c7b6fc811..a1468e3f5af24e33acbfaa392db9770cea249668 100644 (file)
@@ -56,6 +56,7 @@ struct htab_elem {
                        union {
                                struct bpf_htab *htab;
                                struct pcpu_freelist_node fnode;
+                               struct htab_elem *batch_flink;
                        };
                };
        };
@@ -126,6 +127,17 @@ free_elems:
        bpf_map_area_free(htab->elems);
 }
 
+/* The LRU list has a lock (lru_lock). Each htab bucket has a lock
+ * (bucket_lock). If both locks need to be acquired together, the lock
+ * order is always lru_lock -> bucket_lock and this only happens in
+ * bpf_lru_list.c logic. For example, certain code path of
+ * bpf_lru_pop_free(), which is called by function prealloc_lru_pop(),
+ * will acquire lru_lock first followed by acquiring bucket_lock.
+ *
+ * In hashtab.c, to avoid deadlock, lock acquisition of
+ * bucket_lock followed by lru_lock is not allowed. In such cases,
+ * bucket_lock needs to be released first before acquiring lru_lock.
+ */
 static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
                                          u32 hash)
 {
@@ -1256,10 +1268,12 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
        void __user *ukeys = u64_to_user_ptr(attr->batch.keys);
        void *ubatch = u64_to_user_ptr(attr->batch.in_batch);
        u32 batch, max_count, size, bucket_size;
+       struct htab_elem *node_to_free = NULL;
        u64 elem_map_flags, map_flags;
        struct hlist_nulls_head *head;
        struct hlist_nulls_node *n;
-       unsigned long flags;
+       unsigned long flags = 0;
+       bool locked = false;
        struct htab_elem *l;
        struct bucket *b;
        int ret = 0;
@@ -1319,15 +1333,25 @@ again_nocopy:
        dst_val = values;
        b = &htab->buckets[batch];
        head = &b->head;
-       raw_spin_lock_irqsave(&b->lock, flags);
+       /* do not grab the lock unless need it (bucket_cnt > 0). */
+       if (locked)
+               raw_spin_lock_irqsave(&b->lock, flags);
 
        bucket_cnt = 0;
        hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
                bucket_cnt++;
 
+       if (bucket_cnt && !locked) {
+               locked = true;
+               goto again_nocopy;
+       }
+
        if (bucket_cnt > (max_count - total)) {
                if (total == 0)
                        ret = -ENOSPC;
+               /* Note that since bucket_cnt > 0 here, it is implicit
+                * that the locked was grabbed, so release it.
+                */
                raw_spin_unlock_irqrestore(&b->lock, flags);
                rcu_read_unlock();
                this_cpu_dec(bpf_prog_active);
@@ -1337,6 +1361,9 @@ again_nocopy:
 
        if (bucket_cnt > bucket_size) {
                bucket_size = bucket_cnt;
+               /* Note that since bucket_cnt > 0 here, it is implicit
+                * that the locked was grabbed, so release it.
+                */
                raw_spin_unlock_irqrestore(&b->lock, flags);
                rcu_read_unlock();
                this_cpu_dec(bpf_prog_active);
@@ -1346,6 +1373,10 @@ again_nocopy:
                goto alloc;
        }
 
+       /* Next block is only safe to run if you have grabbed the lock */
+       if (!locked)
+               goto next_batch;
+
        hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
                memcpy(dst_key, l->key, key_size);
 
@@ -1370,16 +1401,33 @@ again_nocopy:
                }
                if (do_delete) {
                        hlist_nulls_del_rcu(&l->hash_node);
-                       if (is_lru_map)
-                               bpf_lru_push_free(&htab->lru, &l->lru_node);
-                       else
+
+                       /* bpf_lru_push_free() will acquire lru_lock, which
+                        * may cause deadlock. See comments in function
+                        * prealloc_lru_pop(). Let us do bpf_lru_push_free()
+                        * after releasing the bucket lock.
+                        */
+                       if (is_lru_map) {
+                               l->batch_flink = node_to_free;
+                               node_to_free = l;
+                       } else {
                                free_htab_elem(htab, l);
+                       }
                }
                dst_key += key_size;
                dst_val += value_size;
        }
 
        raw_spin_unlock_irqrestore(&b->lock, flags);
+       locked = false;
+
+       while (node_to_free) {
+               l = node_to_free;
+               node_to_free = node_to_free->batch_flink;
+               bpf_lru_push_free(&htab->lru, &l->lru_node);
+       }
+
+next_batch:
        /* If we are not copying data, we can go to next bucket and avoid
         * unlocking the rcu.
         */
index 2c5dc6541eceed031acd4b0953d29b8f2a48870a..bd09290e364844a35a3c80bc56a63037356c9966 100644 (file)
@@ -321,7 +321,7 @@ int bpf_prog_offload_info_fill(struct bpf_prog_info *info,
 
        ulen = info->jited_prog_len;
        info->jited_prog_len = aux->offload->jited_len;
-       if (info->jited_prog_len & ulen) {
+       if (info->jited_prog_len && ulen) {
                uinsns = u64_to_user_ptr(info->jited_prog_insns);
                ulen = min_t(u32, info->jited_prog_len, ulen);
                if (copy_to_user(uinsns, aux->offload->jited_image, ulen)) {
index 95005f849c68f372e0e9b92d7926ea711d5600fa..843dd17e6078b6d530ecc46260703b390f9abbe4 100644 (file)
 
 #include <linux/uaccess.h>
 
-static int __compat_get_timeval(struct timeval *tv, const struct old_timeval32 __user *ctv)
-{
-       return (!access_ok(ctv, sizeof(*ctv)) ||
-                       __get_user(tv->tv_sec, &ctv->tv_sec) ||
-                       __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
-}
-
-static int __compat_put_timeval(const struct timeval *tv, struct old_timeval32 __user *ctv)
-{
-       return (!access_ok(ctv, sizeof(*ctv)) ||
-                       __put_user(tv->tv_sec, &ctv->tv_sec) ||
-                       __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
-}
-
-static int __compat_get_timespec(struct timespec *ts, const struct old_timespec32 __user *cts)
-{
-       return (!access_ok(cts, sizeof(*cts)) ||
-                       __get_user(ts->tv_sec, &cts->tv_sec) ||
-                       __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
-}
-
-static int __compat_put_timespec(const struct timespec *ts, struct old_timespec32 __user *cts)
-{
-       return (!access_ok(cts, sizeof(*cts)) ||
-                       __put_user(ts->tv_sec, &cts->tv_sec) ||
-                       __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
-}
-
-int compat_get_timeval(struct timeval *tv, const void __user *utv)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_from_user(tv, utv, sizeof(*tv)) ? -EFAULT : 0;
-       else
-               return __compat_get_timeval(tv, utv);
-}
-EXPORT_SYMBOL_GPL(compat_get_timeval);
-
-int compat_put_timeval(const struct timeval *tv, void __user *utv)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_to_user(utv, tv, sizeof(*tv)) ? -EFAULT : 0;
-       else
-               return __compat_put_timeval(tv, utv);
-}
-EXPORT_SYMBOL_GPL(compat_put_timeval);
-
-int compat_get_timespec(struct timespec *ts, const void __user *uts)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
-       else
-               return __compat_get_timespec(ts, uts);
-}
-EXPORT_SYMBOL_GPL(compat_get_timespec);
-
-int compat_put_timespec(const struct timespec *ts, void __user *uts)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
-       else
-               return __compat_put_timespec(ts, uts);
-}
-EXPORT_SYMBOL_GPL(compat_put_timespec);
-
 #ifdef __ARCH_WANT_SYS_SIGPROCMASK
 
 /*
index daa4e6eefdde86e898668b3c9ebdb55b2c6b59f3..8bc6f2d670f956f24f4786b7dafb1d49b69beb85 100644 (file)
@@ -302,9 +302,16 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
        phys_addr_t mask = align - 1;
        unsigned long node = rmem->fdt_node;
+       bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
        struct cma *cma;
        int err;
 
+       if (size_cmdline != -1 && default_cma) {
+               pr_info("Reserved memory: bypass %s node, using cmdline CMA params instead\n",
+                       rmem->name);
+               return -EBUSY;
+       }
+
        if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
            of_get_flat_dt_prop(node, "no-map", NULL))
                return -EINVAL;
@@ -322,7 +329,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        /* Architecture specific contiguous memory fixup. */
        dma_contiguous_early_fixup(rmem->base, rmem->size);
 
-       if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
+       if (default_cma)
                dma_contiguous_set_default(cma);
 
        rmem->ops = &rmem_cma_ops;
index 6af7ae83c4ada1534bcf7dc203de907515e24fea..ac7956c38f693f2bc6346411ff2b097a003967dd 100644 (file)
  */
 unsigned int zone_dma_bits __ro_after_init = 24;
 
-static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
-       if (!dev->dma_mask) {
-               dev_err_once(dev, "DMA map on device without dma_mask\n");
-       } else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_limit) {
-               dev_err_once(dev,
-                       "overflow %pad+%zu of DMA mask %llx bus limit %llx\n",
-                       &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
-       }
-       WARN_ON_ONCE(1);
-}
-
 static inline dma_addr_t phys_to_dma_direct(struct device *dev,
                phys_addr_t phys)
 {
@@ -357,13 +345,6 @@ void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sgl,
 EXPORT_SYMBOL(dma_direct_unmap_sg);
 #endif
 
-static inline bool dma_direct_possible(struct device *dev, dma_addr_t dma_addr,
-               size_t size)
-{
-       return swiotlb_force != SWIOTLB_FORCE &&
-               dma_capable(dev, dma_addr, size, true);
-}
-
 dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size, enum dma_data_direction dir,
                unsigned long attrs)
@@ -371,9 +352,16 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
        phys_addr_t phys = page_to_phys(page) + offset;
        dma_addr_t dma_addr = phys_to_dma(dev, phys);
 
-       if (unlikely(!dma_direct_possible(dev, dma_addr, size)) &&
-           !swiotlb_map(dev, &phys, &dma_addr, size, dir, attrs)) {
-               report_addr(dev, dma_addr, size);
+       if (unlikely(swiotlb_force == SWIOTLB_FORCE))
+               return swiotlb_map(dev, phys, size, dir, attrs);
+
+       if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
+               if (swiotlb_force != SWIOTLB_NO_FORCE)
+                       return swiotlb_map(dev, phys, size, dir, attrs);
+
+               dev_WARN_ONCE(dev, 1,
+                            "DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                            &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
                return DMA_MAPPING_ERROR;
        }
 
@@ -411,7 +399,10 @@ dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
        dma_addr_t dma_addr = paddr;
 
        if (unlikely(!dma_capable(dev, dma_addr, size, false))) {
-               report_addr(dev, dma_addr, size);
+               dev_err_once(dev,
+                            "DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                            &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
+               WARN_ON_ONCE(1);
                return DMA_MAPPING_ERROR;
        }
 
@@ -472,28 +463,26 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
 }
 #endif /* CONFIG_MMU */
 
-/*
- * Because 32-bit DMA masks are so common we expect every architecture to be
- * able to satisfy them - either by not supporting more physical memory, or by
- * providing a ZONE_DMA32.  If neither is the case, the architecture needs to
- * use an IOMMU instead of the direct mapping.
- */
 int dma_direct_supported(struct device *dev, u64 mask)
 {
-       u64 min_mask;
+       u64 min_mask = (max_pfn - 1) << PAGE_SHIFT;
 
-       if (IS_ENABLED(CONFIG_ZONE_DMA))
-               min_mask = DMA_BIT_MASK(zone_dma_bits);
-       else
-               min_mask = DMA_BIT_MASK(32);
-
-       min_mask = min_t(u64, min_mask, (max_pfn - 1) << PAGE_SHIFT);
+       /*
+        * Because 32-bit DMA masks are so common we expect every architecture
+        * to be able to satisfy them - either by not supporting more physical
+        * memory, or by providing a ZONE_DMA32.  If neither is the case, the
+        * architecture needs to use an IOMMU instead of the direct mapping.
+        */
+       if (mask >= DMA_BIT_MASK(32))
+               return 1;
 
        /*
         * This check needs to be against the actual bit mask value, so
         * use __phys_to_dma() here so that the SME encryption mask isn't
         * part of the check.
         */
+       if (IS_ENABLED(CONFIG_ZONE_DMA))
+               min_mask = min_t(u64, min_mask, DMA_BIT_MASK(zone_dma_bits));
        return mask >= __phys_to_dma(dev, min_mask);
 }
 
index 9280d6f8271ed4360bab41cfb2d8dc66d75ca203..c19379fabd200ebb13c5a134b4f366291751982b 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/cache.h>
 #include <linux/dma-direct.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
@@ -656,35 +657,38 @@ void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr,
 }
 
 /*
- * Create a swiotlb mapping for the buffer at @phys, and in case of DMAing
+ * Create a swiotlb mapping for the buffer at @paddr, and in case of DMAing
  * to the device copy the data into it as well.
  */
-bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
-               size_t size, enum dma_data_direction dir, unsigned long attrs)
+dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
+               enum dma_data_direction dir, unsigned long attrs)
 {
-       trace_swiotlb_bounced(dev, *dma_addr, size, swiotlb_force);
+       phys_addr_t swiotlb_addr;
+       dma_addr_t dma_addr;
 
-       if (unlikely(swiotlb_force == SWIOTLB_NO_FORCE)) {
-               dev_warn_ratelimited(dev,
-                       "Cannot do DMA to address %pa\n", phys);
-               return false;
-       }
+       trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size,
+                             swiotlb_force);
 
-       /* Oh well, have to allocate and map a bounce buffer. */
-       *phys = swiotlb_tbl_map_single(dev, __phys_to_dma(dev, io_tlb_start),
-                       *phys, size, size, dir, attrs);
-       if (*phys == (phys_addr_t)DMA_MAPPING_ERROR)
-               return false;
+       swiotlb_addr = swiotlb_tbl_map_single(dev,
+                       __phys_to_dma(dev, io_tlb_start),
+                       paddr, size, size, dir, attrs);
+       if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR)
+               return DMA_MAPPING_ERROR;
 
        /* Ensure that the address returned is DMA'ble */
-       *dma_addr = __phys_to_dma(dev, *phys);
-       if (unlikely(!dma_capable(dev, *dma_addr, size, true))) {
-               swiotlb_tbl_unmap_single(dev, *phys, size, size, dir,
+       dma_addr = __phys_to_dma(dev, swiotlb_addr);
+       if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
+               swiotlb_tbl_unmap_single(dev, swiotlb_addr, size, size, dir,
                        attrs | DMA_ATTR_SKIP_CPU_SYNC);
-               return false;
+               dev_WARN_ONCE(dev, 1,
+                       "swiotlb addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                       &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
+               return DMA_MAPPING_ERROR;
        }
 
-       return true;
+       if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+               arch_sync_dma_for_device(swiotlb_addr, size, dir);
+       return dma_addr;
 }
 
 size_t swiotlb_max_mapping_size(struct device *dev)
index 3924fbe829d4a8aeaa32750580212b0f008d7f39..c9d8eb7f5c029244b4db5f68cae4463412064077 100644 (file)
@@ -128,8 +128,6 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 extern bool irq_can_set_affinity_usr(unsigned int irq);
 
-extern int irq_select_affinity_usr(unsigned int irq);
-
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
 extern int irq_do_set_affinity(struct irq_data *data,
index 3089a60ea8f98ffeb58c0d497d1172cc15718e1e..7eee98c38f25ca20047ed75c268fae4550949bdd 100644 (file)
@@ -481,23 +481,9 @@ int irq_setup_affinity(struct irq_desc *desc)
 {
        return irq_select_affinity(irq_desc_get_irq(desc));
 }
-#endif
+#endif /* CONFIG_AUTO_IRQ_AFFINITY */
+#endif /* CONFIG_SMP */
 
-/*
- * Called when a bogus affinity is set via /proc/irq
- */
-int irq_select_affinity_usr(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned long flags;
-       int ret;
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       ret = irq_setup_affinity(desc);
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-       return ret;
-}
-#endif
 
 /**
  *     irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
index 9e5783d98033ee183e389ca9efa3681e0b642743..32c071d7bc0338ac73253c586e04de7fc816a873 100644 (file)
@@ -111,6 +111,28 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
        return show_irq_affinity(AFFINITY_LIST, m);
 }
 
+#ifndef CONFIG_AUTO_IRQ_AFFINITY
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       /*
+        * If the interrupt is started up already then this fails. The
+        * interrupt is assigned to an online CPU already. There is no
+        * point to move it around randomly. Tell user space that the
+        * selected mask is bogus.
+        *
+        * If not then any change to the affinity is pointless because the
+        * startup code invokes irq_setup_affinity() which will select
+        * a online CPU anyway.
+        */
+       return -EINVAL;
+}
+#else
+/* ALPHA magic affinity auto selector. Keep it for historical reasons. */
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       return irq_select_affinity(irq);
+}
+#endif
 
 static ssize_t write_irq_affinity(int type, struct file *file,
                const char __user *buffer, size_t count, loff_t *pos)
index ddade80ad27670c33f84bbbedd1328edf42a3ace..d82b7b88d616ee4ea792d6ec6340dd46f00a42ad 100644 (file)
@@ -1681,7 +1681,7 @@ static unsigned long minimum_image_size(unsigned long saveable)
  * hibernation for allocations made while saving the image and for device
  * drivers, in case they need to allocate memory from their hibernation
  * callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough
- * estimate) and reserverd_size divided by PAGE_SIZE (which is tunable through
+ * estimate) and reserved_size divided by PAGE_SIZE (which is tunable through
  * /sys/power/reserved_size, respectively).  To make this happen, we compute the
  * total number of available page frames and allocate at least
  *
index 9ad8dea93dbb23482d18b24c3be220cb775f80eb..5b2396350dd183cc3ce04d115763cc590d5e3cc0 100644 (file)
@@ -413,27 +413,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
 {
        struct sigqueue *q = NULL;
        struct user_struct *user;
+       int sigpending;
 
        /*
         * Protect access to @t credentials. This can go away when all
         * callers hold rcu read lock.
+        *
+        * NOTE! A pending signal will hold on to the user refcount,
+        * and we get/put the refcount only when the sigpending count
+        * changes from/to zero.
         */
        rcu_read_lock();
-       user = get_uid(__task_cred(t)->user);
-       atomic_inc(&user->sigpending);
+       user = __task_cred(t)->user;
+       sigpending = atomic_inc_return(&user->sigpending);
+       if (sigpending == 1)
+               get_uid(user);
        rcu_read_unlock();
 
-       if (override_rlimit ||
-           atomic_read(&user->sigpending) <=
-                       task_rlimit(t, RLIMIT_SIGPENDING)) {
+       if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {
                q = kmem_cache_alloc(sigqueue_cachep, flags);
        } else {
                print_dropped_signal(sig);
        }
 
        if (unlikely(q == NULL)) {
-               atomic_dec(&user->sigpending);
-               free_uid(user);
+               if (atomic_dec_and_test(&user->sigpending))
+                       free_uid(user);
        } else {
                INIT_LIST_HEAD(&q->list);
                q->flags = 0;
@@ -447,8 +452,8 @@ static void __sigqueue_free(struct sigqueue *q)
 {
        if (q->flags & SIGQUEUE_PREALLOC)
                return;
-       atomic_dec(&q->user->sigpending);
-       free_uid(q->user);
+       if (atomic_dec_and_test(&q->user->sigpending))
+               free_uid(q->user);
        kmem_cache_free(sigqueue_cachep, q);
 }
 
index d396aaaf19a329203e4e03dfaa3f33fffa93e0f1..ad5b88a53c5a87528c77bb1f2e8cac25de2e75d3 100644 (file)
@@ -805,15 +805,6 @@ static struct ctl_table kern_table[] = {
                .extra2         = &maxolduid,
        },
 #ifdef CONFIG_S390
-#ifdef CONFIG_MATHEMU
-       {
-               .procname       = "ieee_emulation_warnings",
-               .data           = &sysctl_ieee_emulation_warnings,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
-#endif
        {
                .procname       = "userprocess_debug",
                .data           = &show_unhandled_signals,
index cdd7386115ff9de912b4ad405640ee391d9178d9..3985b2b32d083e06acfee3c83f952426660dbe9d 100644 (file)
@@ -449,49 +449,6 @@ time64_t mktime64(const unsigned int year0, const unsigned int mon0,
 }
 EXPORT_SYMBOL(mktime64);
 
-/**
- * ns_to_timespec - Convert nanoseconds to timespec
- * @nsec:       the nanoseconds value to be converted
- *
- * Returns the timespec representation of the nsec parameter.
- */
-struct timespec ns_to_timespec(const s64 nsec)
-{
-       struct timespec ts;
-       s32 rem;
-
-       if (!nsec)
-               return (struct timespec) {0, 0};
-
-       ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
-       if (unlikely(rem < 0)) {
-               ts.tv_sec--;
-               rem += NSEC_PER_SEC;
-       }
-       ts.tv_nsec = rem;
-
-       return ts;
-}
-EXPORT_SYMBOL(ns_to_timespec);
-
-/**
- * ns_to_timeval - Convert nanoseconds to timeval
- * @nsec:       the nanoseconds value to be converted
- *
- * Returns the timeval representation of the nsec parameter.
- */
-struct timeval ns_to_timeval(const s64 nsec)
-{
-       struct timespec ts = ns_to_timespec(nsec);
-       struct timeval tv;
-
-       tv.tv_sec = ts.tv_sec;
-       tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000;
-
-       return tv;
-}
-EXPORT_SYMBOL(ns_to_timeval);
-
 struct __kernel_old_timeval ns_to_kernel_old_timeval(const s64 nsec)
 {
        struct timespec64 ts = ns_to_timespec64(nsec);
index 91e885194dbce47f7f75bbda244aadcca8672986..402eef84c859ac0b7356ca89f22446b00e0b757e 100644 (file)
@@ -143,8 +143,8 @@ if FTRACE
 
 config BOOTTIME_TRACING
        bool "Boot-time Tracing support"
-       depends on BOOT_CONFIG && TRACING
-       default y
+       depends on TRACING
+       select BOOT_CONFIG
        help
          Enable developer to setup ftrace subsystem via supplemental
          kernel cmdline at boot time for debugging (tracing) driver
index 0735ae8545d86a21d5595392e5b7805b4d75ad13..4560878f0bac01f78a038c34158c2d91d8eba37c 100644 (file)
@@ -335,6 +335,7 @@ static void put_probe_ref(void)
 
 static void blk_trace_cleanup(struct blk_trace *bt)
 {
+       synchronize_rcu();
        blk_trace_free(bt);
        put_probe_ref();
 }
@@ -629,8 +630,10 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
 static int __blk_trace_startstop(struct request_queue *q, int start)
 {
        int ret;
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
+       bt = rcu_dereference_protected(q->blk_trace,
+                                      lockdep_is_held(&q->blk_trace_mutex));
        if (bt == NULL)
                return -EINVAL;
 
@@ -740,8 +743,8 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
 void blk_trace_shutdown(struct request_queue *q)
 {
        mutex_lock(&q->blk_trace_mutex);
-
-       if (q->blk_trace) {
+       if (rcu_dereference_protected(q->blk_trace,
+                                     lockdep_is_held(&q->blk_trace_mutex))) {
                __blk_trace_startstop(q, 0);
                __blk_trace_remove(q);
        }
@@ -752,8 +755,10 @@ void blk_trace_shutdown(struct request_queue *q)
 #ifdef CONFIG_BLK_CGROUP
 static u64 blk_trace_bio_get_cgid(struct request_queue *q, struct bio *bio)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
+       /* We don't use the 'bt' value here except as an optimization... */
+       bt = rcu_dereference_protected(q->blk_trace, 1);
        if (!bt || !(blk_tracer_flags.val & TRACE_BLK_OPT_CGROUP))
                return 0;
 
@@ -796,10 +801,14 @@ blk_trace_request_get_cgid(struct request_queue *q, struct request *rq)
 static void blk_add_trace_rq(struct request *rq, int error,
                             unsigned int nr_bytes, u32 what, u64 cgid)
 {
-       struct blk_trace *bt = rq->q->blk_trace;
+       struct blk_trace *bt;
 
-       if (likely(!bt))
+       rcu_read_lock();
+       bt = rcu_dereference(rq->q->blk_trace);
+       if (likely(!bt)) {
+               rcu_read_unlock();
                return;
+       }
 
        if (blk_rq_is_passthrough(rq))
                what |= BLK_TC_ACT(BLK_TC_PC);
@@ -808,6 +817,7 @@ static void blk_add_trace_rq(struct request *rq, int error,
 
        __blk_add_trace(bt, blk_rq_trace_sector(rq), nr_bytes, req_op(rq),
                        rq->cmd_flags, what, error, 0, NULL, cgid);
+       rcu_read_unlock();
 }
 
 static void blk_add_trace_rq_insert(void *ignore,
@@ -853,14 +863,19 @@ static void blk_add_trace_rq_complete(void *ignore, struct request *rq,
 static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
                              u32 what, int error)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
-       if (likely(!bt))
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
+       if (likely(!bt)) {
+               rcu_read_unlock();
                return;
+       }
 
        __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
                        bio_op(bio), bio->bi_opf, what, error, 0, NULL,
                        blk_trace_bio_get_cgid(q, bio));
+       rcu_read_unlock();
 }
 
 static void blk_add_trace_bio_bounce(void *ignore,
@@ -905,11 +920,14 @@ static void blk_add_trace_getrq(void *ignore,
        if (bio)
                blk_add_trace_bio(q, bio, BLK_TA_GETRQ, 0);
        else {
-               struct blk_trace *bt = q->blk_trace;
+               struct blk_trace *bt;
 
+               rcu_read_lock();
+               bt = rcu_dereference(q->blk_trace);
                if (bt)
                        __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_GETRQ, 0, 0,
                                        NULL, 0);
+               rcu_read_unlock();
        }
 }
 
@@ -921,27 +939,35 @@ static void blk_add_trace_sleeprq(void *ignore,
        if (bio)
                blk_add_trace_bio(q, bio, BLK_TA_SLEEPRQ, 0);
        else {
-               struct blk_trace *bt = q->blk_trace;
+               struct blk_trace *bt;
 
+               rcu_read_lock();
+               bt = rcu_dereference(q->blk_trace);
                if (bt)
                        __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_SLEEPRQ,
                                        0, 0, NULL, 0);
+               rcu_read_unlock();
        }
 }
 
 static void blk_add_trace_plug(void *ignore, struct request_queue *q)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
        if (bt)
                __blk_add_trace(bt, 0, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL, 0);
+       rcu_read_unlock();
 }
 
 static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
                                    unsigned int depth, bool explicit)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
        if (bt) {
                __be64 rpdu = cpu_to_be64(depth);
                u32 what;
@@ -953,14 +979,17 @@ static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
 
                __blk_add_trace(bt, 0, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu, 0);
        }
+       rcu_read_unlock();
 }
 
 static void blk_add_trace_split(void *ignore,
                                struct request_queue *q, struct bio *bio,
                                unsigned int pdu)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
        if (bt) {
                __be64 rpdu = cpu_to_be64(pdu);
 
@@ -969,6 +998,7 @@ static void blk_add_trace_split(void *ignore,
                                BLK_TA_SPLIT, bio->bi_status, sizeof(rpdu),
                                &rpdu, blk_trace_bio_get_cgid(q, bio));
        }
+       rcu_read_unlock();
 }
 
 /**
@@ -988,11 +1018,15 @@ static void blk_add_trace_bio_remap(void *ignore,
                                    struct request_queue *q, struct bio *bio,
                                    dev_t dev, sector_t from)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
        struct blk_io_trace_remap r;
 
-       if (likely(!bt))
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
+       if (likely(!bt)) {
+               rcu_read_unlock();
                return;
+       }
 
        r.device_from = cpu_to_be32(dev);
        r.device_to   = cpu_to_be32(bio_dev(bio));
@@ -1001,6 +1035,7 @@ static void blk_add_trace_bio_remap(void *ignore,
        __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
                        bio_op(bio), bio->bi_opf, BLK_TA_REMAP, bio->bi_status,
                        sizeof(r), &r, blk_trace_bio_get_cgid(q, bio));
+       rcu_read_unlock();
 }
 
 /**
@@ -1021,11 +1056,15 @@ static void blk_add_trace_rq_remap(void *ignore,
                                   struct request *rq, dev_t dev,
                                   sector_t from)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
        struct blk_io_trace_remap r;
 
-       if (likely(!bt))
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
+       if (likely(!bt)) {
+               rcu_read_unlock();
                return;
+       }
 
        r.device_from = cpu_to_be32(dev);
        r.device_to   = cpu_to_be32(disk_devt(rq->rq_disk));
@@ -1034,6 +1073,7 @@ static void blk_add_trace_rq_remap(void *ignore,
        __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq),
                        rq_data_dir(rq), 0, BLK_TA_REMAP, 0,
                        sizeof(r), &r, blk_trace_request_get_cgid(q, rq));
+       rcu_read_unlock();
 }
 
 /**
@@ -1051,14 +1091,19 @@ void blk_add_driver_data(struct request_queue *q,
                         struct request *rq,
                         void *data, size_t len)
 {
-       struct blk_trace *bt = q->blk_trace;
+       struct blk_trace *bt;
 
-       if (likely(!bt))
+       rcu_read_lock();
+       bt = rcu_dereference(q->blk_trace);
+       if (likely(!bt)) {
+               rcu_read_unlock();
                return;
+       }
 
        __blk_add_trace(bt, blk_rq_trace_sector(rq), blk_rq_bytes(rq), 0, 0,
                                BLK_TA_DRV_DATA, 0, len, data,
                                blk_trace_request_get_cgid(q, rq));
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(blk_add_driver_data);
 
@@ -1597,6 +1642,7 @@ static int blk_trace_remove_queue(struct request_queue *q)
                return -EINVAL;
 
        put_probe_ref();
+       synchronize_rcu();
        blk_trace_free(bt);
        return 0;
 }
@@ -1758,6 +1804,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
        struct hd_struct *p = dev_to_part(dev);
        struct request_queue *q;
        struct block_device *bdev;
+       struct blk_trace *bt;
        ssize_t ret = -ENXIO;
 
        bdev = bdget(part_devt(p));
@@ -1770,21 +1817,23 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
 
        mutex_lock(&q->blk_trace_mutex);
 
+       bt = rcu_dereference_protected(q->blk_trace,
+                                      lockdep_is_held(&q->blk_trace_mutex));
        if (attr == &dev_attr_enable) {
-               ret = sprintf(buf, "%u\n", !!q->blk_trace);
+               ret = sprintf(buf, "%u\n", !!bt);
                goto out_unlock_bdev;
        }
 
-       if (q->blk_trace == NULL)
+       if (bt == NULL)
                ret = sprintf(buf, "disabled\n");
        else if (attr == &dev_attr_act_mask)
-               ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
+               ret = blk_trace_mask2str(buf, bt->act_mask);
        else if (attr == &dev_attr_pid)
-               ret = sprintf(buf, "%u\n", q->blk_trace->pid);
+               ret = sprintf(buf, "%u\n", bt->pid);
        else if (attr == &dev_attr_start_lba)
-               ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
+               ret = sprintf(buf, "%llu\n", bt->start_lba);
        else if (attr == &dev_attr_end_lba)
-               ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
+               ret = sprintf(buf, "%llu\n", bt->end_lba);
 
 out_unlock_bdev:
        mutex_unlock(&q->blk_trace_mutex);
@@ -1801,6 +1850,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
        struct block_device *bdev;
        struct request_queue *q;
        struct hd_struct *p;
+       struct blk_trace *bt;
        u64 value;
        ssize_t ret = -EINVAL;
 
@@ -1831,8 +1881,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
 
        mutex_lock(&q->blk_trace_mutex);
 
+       bt = rcu_dereference_protected(q->blk_trace,
+                                      lockdep_is_held(&q->blk_trace_mutex));
        if (attr == &dev_attr_enable) {
-               if (!!value == !!q->blk_trace) {
+               if (!!value == !!bt) {
                        ret = 0;
                        goto out_unlock_bdev;
                }
@@ -1844,18 +1896,18 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
        }
 
        ret = 0;
-       if (q->blk_trace == NULL)
+       if (bt == NULL)
                ret = blk_trace_setup_queue(q, bdev);
 
        if (ret == 0) {
                if (attr == &dev_attr_act_mask)
-                       q->blk_trace->act_mask = value;
+                       bt->act_mask = value;
                else if (attr == &dev_attr_pid)
-                       q->blk_trace->pid = value;
+                       bt->pid = value;
                else if (attr == &dev_attr_start_lba)
-                       q->blk_trace->start_lba = value;
+                       bt->start_lba = value;
                else if (attr == &dev_attr_end_lba)
-                       q->blk_trace->end_lba = value;
+                       bt->end_lba = value;
        }
 
 out_unlock_bdev:
index 4aefe003cb7c3415685f6a9eb31c7f3a3f29fb87..7d56d621ffea879e91ac127475527173dc745380 100644 (file)
@@ -111,11 +111,11 @@ static int __init test_gen_synth_cmd(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"hula hoops";    /* next_comm_field */
+       vals[1] = (u64)(long)"hula hoops";      /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 598;                  /* my_int_field */
 
        /* Now generate a gen_synth_test event */
@@ -218,11 +218,11 @@ static int __init test_empty_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed_2.0";    /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed_2.0";      /* my_string_field */
        vals[6] = 399;                  /* my_int_field */
 
        /* Now trace an empty_synth_test event */
@@ -290,11 +290,11 @@ static int __init test_create_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 398;                  /* my_int_field */
 
        /* Now generate a create_synth_test event */
@@ -330,7 +330,7 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* next_comm_field */
-       ret = synth_event_add_next_val((u64)"slinky", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"slinky", &trace_state);
        if (ret)
                goto out;
 
@@ -345,12 +345,12 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* cpu */
-       ret = synth_event_add_next_val(smp_processor_id(), &trace_state);
+       ret = synth_event_add_next_val(raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
        /* my_string_field */
-       ret = synth_event_add_next_val((u64)"thneed_2.01", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"thneed_2.01", &trace_state);
        if (ret)
                goto out;
 
@@ -388,7 +388,7 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("cpu", smp_processor_id(), &trace_state);
+       ret = synth_event_add_val("cpu", raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
@@ -396,12 +396,12 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("next_comm_field", (u64)"silly putty",
+       ret = synth_event_add_val("next_comm_field", (u64)(long)"silly putty",
                                  &trace_state);
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("my_string_field", (u64)"thneed_9",
+       ret = synth_event_add_val("my_string_field", (u64)(long)"thneed_9",
                                  &trace_state);
        if (ret)
                goto out;
@@ -423,13 +423,13 @@ static int __init test_trace_synth_event(void)
 
        /* Trace some bogus values just for testing */
        ret = synth_event_trace(create_synth_test, 7,   /* number of values */
-                               444,                    /* next_pid_field */
-                               (u64)"clackers",        /* next_comm_field */
-                               1000000,                /* ts_ns */
-                               1000,                   /* ts_ms */
-                               smp_processor_id(),     /* cpu */
-                               (u64)"Thneed",          /* my_string_field */
-                               999);                   /* my_int_field */
+                               (u64)444,               /* next_pid_field */
+                               (u64)(long)"clackers",  /* next_comm_field */
+                               (u64)1000000,           /* ts_ns */
+                               (u64)1000,              /* ts_ms */
+                               (u64)raw_smp_processor_id(), /* cpu */
+                               (u64)(long)"Thneed",    /* my_string_field */
+                               (u64)999);              /* my_int_field */
        return ret;
 }
 
index c797a15a1fc77ef672c0269d3e9a2048f168edd2..6b11e4e2150cea92de1f4c007efe4ea9c0c219e8 100644 (file)
@@ -1837,6 +1837,7 @@ static __init int init_trace_selftests(void)
 
        pr_info("Running postponed tracer tests:\n");
 
+       tracing_selftest_running = true;
        list_for_each_entry_safe(p, n, &postponed_selftests, list) {
                /* This loop can take minutes when sanitizers are enabled, so
                 * lets make sure we allow RCU processing.
@@ -1859,6 +1860,7 @@ static __init int init_trace_selftests(void)
                list_del(&p->list);
                kfree(p);
        }
+       tracing_selftest_running = false;
 
  out:
        mutex_unlock(&trace_types_lock);
index 483b3fd1094f3b17f9df87eeee0448f43f62cf5b..5f6834a2bf4119ef4a30879cac479e0cbc0e5bdf 100644 (file)
@@ -821,6 +821,29 @@ static const char *synth_field_fmt(char *type)
        return fmt;
 }
 
+static void print_synth_event_num_val(struct trace_seq *s,
+                                     char *print_fmt, char *name,
+                                     int size, u64 val, char *space)
+{
+       switch (size) {
+       case 1:
+               trace_seq_printf(s, print_fmt, name, (u8)val, space);
+               break;
+
+       case 2:
+               trace_seq_printf(s, print_fmt, name, (u16)val, space);
+               break;
+
+       case 4:
+               trace_seq_printf(s, print_fmt, name, (u32)val, space);
+               break;
+
+       default:
+               trace_seq_printf(s, print_fmt, name, val, space);
+               break;
+       }
+}
+
 static enum print_line_t print_synth_event(struct trace_iterator *iter,
                                           int flags,
                                           struct trace_event *event)
@@ -859,10 +882,13 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter,
                } else {
                        struct trace_print_flags __flags[] = {
                            __def_gfpflag_names, {-1, NULL} };
+                       char *space = (i == se->n_fields - 1 ? "" : " ");
 
-                       trace_seq_printf(s, print_fmt, se->fields[i]->name,
-                                        entry->fields[n_u64],
-                                        i == se->n_fields - 1 ? "" : " ");
+                       print_synth_event_num_val(s, print_fmt,
+                                                 se->fields[i]->name,
+                                                 se->fields[i]->size,
+                                                 entry->fields[n_u64],
+                                                 space);
 
                        if (strcmp(se->fields[i]->type, "gfp_t") == 0) {
                                trace_seq_puts(s, " (");
@@ -1805,6 +1831,8 @@ __synth_event_trace_start(struct trace_event_file *file,
        int entry_size, fields_size = 0;
        int ret = 0;
 
+       memset(trace_state, '\0', sizeof(*trace_state));
+
        /*
         * Normal event tracing doesn't get called at all unless the
         * ENABLED bit is set (which attaches the probe thus allowing
@@ -1885,6 +1913,11 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        va_start(args, n_vals);
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                u64 val;
@@ -1898,12 +1931,30 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = val;
+                       struct synth_field *field = state.event->fields[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
        va_end(args);
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1942,6 +1993,11 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                if (state.event->fields[i]->is_string) {
                        char *str_val = (char *)(long)vals[i];
@@ -1950,11 +2006,30 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = vals[i];
+                       struct synth_field *field = state.event->fields[i];
+                       u64 val = vals[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1997,8 +2072,6 @@ int synth_event_trace_start(struct trace_event_file *file,
        if (!trace_state)
                return -EINVAL;
 
-       memset(trace_state, '\0', sizeof(*trace_state));
-
        ret = __synth_event_trace_start(file, trace_state);
        if (ret == -ENOENT)
                ret = 0; /* just disabled, not really an error */
@@ -2069,8 +2142,25 @@ static int __synth_event_add_val(const char *field_name, u64 val,
 
                str_field = (char *)&entry->fields[field->offset];
                strscpy(str_field, str_val, STR_VAR_LEN_MAX);
-       } else
-               entry->fields[field->offset] = val;
+       } else {
+               switch (field->size) {
+               case 1:
+                       *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val;
+                       break;
+
+               case 2:
+                       *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val;
+                       break;
+
+               case 4:
+                       *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val;
+                       break;
+
+               default:
+                       trace_state->entry->fields[field->offset] = val;
+                       break;
+               }
+       }
  out:
        return ret;
 }
index 3ea601a2eba5fbdaaabcbca5dc6d7bcdce075732..ec3ce7fd299f6f36ca3a07897b45bf876e0c2db2 100644 (file)
@@ -533,7 +533,7 @@ struct xbc_node *find_match_node(struct xbc_node *node, char *k)
 
 static int __init __xbc_add_key(char *k)
 {
-       struct xbc_node *node;
+       struct xbc_node *node, *child;
 
        if (!xbc_valid_keyword(k))
                return xbc_parse_error("Invalid keyword", k);
@@ -543,8 +543,12 @@ static int __init __xbc_add_key(char *k)
 
        if (!last_parent)       /* the first level */
                node = find_match_node(xbc_nodes, k);
-       else
-               node = find_match_node(xbc_node_get_child(last_parent), k);
+       else {
+               child = xbc_node_get_child(last_parent);
+               if (child && xbc_node_is_value(child))
+                       return xbc_parse_error("Subkey is mixed with value", k);
+               node = find_match_node(child, k);
+       }
 
        if (node)
                last_parent = node;
@@ -574,10 +578,10 @@ static int __init __xbc_parse_keys(char *k)
        return __xbc_add_key(k);
 }
 
-static int __init xbc_parse_kv(char **k, char *v)
+static int __init xbc_parse_kv(char **k, char *v, int op)
 {
        struct xbc_node *prev_parent = last_parent;
-       struct xbc_node *node;
+       struct xbc_node *child;
        char *next;
        int c, ret;
 
@@ -585,12 +589,19 @@ static int __init xbc_parse_kv(char **k, char *v)
        if (ret)
                return ret;
 
+       child = xbc_node_get_child(last_parent);
+       if (child) {
+               if (xbc_node_is_key(child))
+                       return xbc_parse_error("Value is mixed with subkey", v);
+               else if (op == '=')
+                       return xbc_parse_error("Value is redefined", v);
+       }
+
        c = __xbc_parse_value(&v, &next);
        if (c < 0)
                return c;
 
-       node = xbc_add_sibling(v, XBC_VALUE);
-       if (!node)
+       if (!xbc_add_sibling(v, XBC_VALUE))
                return -ENOMEM;
 
        if (c == ',') { /* Array */
@@ -763,7 +774,7 @@ int __init xbc_init(char *buf)
 
        p = buf;
        do {
-               q = strpbrk(p, "{}=;\n#");
+               q = strpbrk(p, "{}=+;\n#");
                if (!q) {
                        p = skip_spaces(p);
                        if (*p != '\0')
@@ -774,8 +785,15 @@ int __init xbc_init(char *buf)
                c = *q;
                *q++ = '\0';
                switch (c) {
+               case '+':
+                       if (*q++ != '=') {
+                               ret = xbc_parse_error("Wrong '+' operator",
+                                                       q - 2);
+                               break;
+                       }
+                       /* Fall through */
                case '=':
-                       ret = xbc_parse_kv(&p, q);
+                       ret = xbc_parse_kv(&p, q, c);
                        break;
                case '{':
                        ret = xbc_open_brace(&p, q);
index 6d83cafebc69ce06b3b37b96f665f3537a0748b5..ad0699ce702f954bbae3aa899b7acda21a289fd2 100644 (file)
@@ -235,6 +235,9 @@ bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
                __le64 lens[2];
        } b __aligned(16);
 
+       if (WARN_ON(src_len > INT_MAX))
+               return false;
+
        chacha_load_key(b.k, key);
 
        b.iv[0] = 0;
index ed717dd08ff37216a7c90a531f23b2eac0e2be1a..81c69c08d1d157189d253a0cbe2a2bbd82cff421 100644 (file)
@@ -83,15 +83,19 @@ static bool init_stack_slab(void **prealloc)
                return true;
        if (stack_slabs[depot_index] == NULL) {
                stack_slabs[depot_index] = *prealloc;
+               *prealloc = NULL;
        } else {
-               stack_slabs[depot_index + 1] = *prealloc;
+               /* If this is the last depot slab, do not touch the next one. */
+               if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) {
+                       stack_slabs[depot_index + 1] = *prealloc;
+                       *prealloc = NULL;
+               }
                /*
                 * This smp_store_release pairs with smp_load_acquire() from
                 * |next_slab_inited| above and in stack_depot_save().
                 */
                smp_store_release(&next_slab_inited, 1);
        }
-       *prealloc = NULL;
        return true;
 }
 
index f607b967d9785b206c135f466ca114367cb4727d..6012c385fb314d810bd8a2ff4f18b9e8a3a517db 100644 (file)
@@ -699,6 +699,14 @@ EXPORT_SYMBOL(sysfs_streq);
  * @n:         number of strings in the array or -1 for NULL terminated arrays
  * @string:    string to match with
  *
+ * This routine will look for a string in an array of strings up to the
+ * n-th element in the array or until the first NULL element.
+ *
+ * Historically the value of -1 for @n, was used to search in arrays that
+ * are NULL terminated. However, the function does not make a distinction
+ * when finishing the search: either @n elements have been compared OR
+ * the first NULL element was found.
+ *
  * Return:
  * index of a @string in the @array if matches, or %-EINVAL otherwise.
  */
@@ -727,6 +735,14 @@ EXPORT_SYMBOL(match_string);
  *
  * Returns index of @str in the @array or -EINVAL, just like match_string().
  * Uses sysfs_streq instead of strcmp for matching.
+ *
+ * This routine will look for a string in an array of strings up to the
+ * n-th element in the array or until the first NULL element.
+ *
+ * Historically the value of -1 for @n, was used to search in arrays that
+ * are NULL terminated. However, the function does not make a distinction
+ * when finishing the search: either @n elements have been compared OR
+ * the first NULL element was found.
  */
 int __sysfs_match_string(const char * const *array, size_t n, const char *str)
 {
index 6f6dc8712e392e5e958868c6bcc191cee3d1e888..d09776cd6e1041d896aa25e726d55f93e46581ed 100644 (file)
@@ -409,8 +409,10 @@ int memcg_expand_shrinker_maps(int new_id)
                if (mem_cgroup_is_root(memcg))
                        continue;
                ret = memcg_expand_one_shrinker_map(memcg, size, old_size);
-               if (ret)
+               if (ret) {
+                       mem_cgroup_iter_break(NULL, memcg);
                        goto unlock;
+               }
        }
 unlock:
        if (!ret)
index 6756b8bb00334c023c73d1a8112785d205e5c927..d681a20eb4ea9fc604caeedbc2b396083360462d 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -195,8 +195,6 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        bool downgraded = false;
        LIST_HEAD(uf);
 
-       brk = untagged_addr(brk);
-
        if (down_write_killable(&mm->mmap_sem))
                return -EINTR;
 
@@ -1557,8 +1555,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
        struct file *file = NULL;
        unsigned long retval;
 
-       addr = untagged_addr(addr);
-
        if (!(flags & MAP_ANONYMOUS)) {
                audit_mmap_fd(fd, flags);
                file = fget(fd);
index 122938dcec15c9a8359d62ceec5801bd74177b3f..af363063ea23bc45430bf5658ca526dd7e053cb7 100644 (file)
@@ -607,7 +607,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
        LIST_HEAD(uf_unmap);
 
        addr = untagged_addr(addr);
-       new_addr = untagged_addr(new_addr);
 
        if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
                return ret;
index c8f7540ef048ebc5b425ed640999acf361819cd7..aad3ba74b0e9d121bd774e795460d5f2f73ac119 100644 (file)
@@ -3386,8 +3386,6 @@ static const struct constant_table shmem_param_enums_huge[] = {
        {"always",      SHMEM_HUGE_ALWAYS },
        {"within_size", SHMEM_HUGE_WITHIN_SIZE },
        {"advise",      SHMEM_HUGE_ADVISE },
-       {"deny",        SHMEM_HUGE_DENY },
-       {"force",       SHMEM_HUGE_FORCE },
        {}
 };
 
index c184b69460b7bd53198a5e31cfd56bf39b0016e5..596b2a45b100507e95d7c7694698c36283113400 100644 (file)
@@ -876,7 +876,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
         * Poison uninitialized struct pages in order to catch invalid flags
         * combinations.
         */
-       page_init_poison(pfn_to_page(start_pfn), sizeof(struct page) * nr_pages);
+       page_init_poison(memmap, sizeof(struct page) * nr_pages);
 
        ms = __nr_to_section(section_nr);
        set_section_nid(section_nr, nid);
index 2c33ff456ed5e228510e02becb6e722f6e6603f0..b2a2e45c9a36f15dee49301aabb9343fe76c36cd 100644 (file)
@@ -3157,7 +3157,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        mapping = swap_file->f_mapping;
        inode = mapping->host;
 
-       /* If S_ISREG(inode->i_mode) will do inode_lock(inode); */
+       /* will take i_rwsem; */
        error = claim_swapfile(p, inode);
        if (unlikely(error))
                goto bad_swap;
index c05eb9efec07f369296756dbd035ed4e59961b98..876370565455e275828d8cde8e8f9cd1819fd759 100644 (file)
@@ -2415,10 +2415,13 @@ out:
                        /*
                         * Scan types proportional to swappiness and
                         * their relative recent reclaim efficiency.
-                        * Make sure we don't miss the last page
-                        * because of a round-off error.
+                        * Make sure we don't miss the last page on
+                        * the offlined memory cgroups because of a
+                        * round-off error.
                         */
-                       scan = DIV64_U64_ROUND_UP(scan * fraction[file],
+                       scan = mem_cgroup_online(memcg) ?
+                              div64_u64(scan * fraction[file], denominator) :
+                              DIV64_U64_ROUND_UP(scan * fraction[file],
                                                  denominator);
                        break;
                case SCAN_FILE:
index b0937a700f018323e5b1e8f0421ee42c825a02d7..2eeb0e55f7c9342dc45f9eb99d438988e1a625dc 100644 (file)
@@ -189,7 +189,6 @@ config BRIDGE_NETFILTER
        depends on NETFILTER_ADVANCED
        select NETFILTER_FAMILY_BRIDGE
        select SKB_EXTENSIONS
-       default m
        ---help---
          Enabling this option will let arptables resp. iptables see bridged
          ARP resp. IP traffic. If you want a bridging firewall, you probably
index dc3d2c1dd9d54ca0a2a9a888b53996bb844b03f9..0e3dbc5f3c34f83203ffafcb944a89fed8043b25 100644 (file)
@@ -34,7 +34,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        const struct nf_br_ops *nf_ops;
        u8 state = BR_STATE_FORWARDING;
        const unsigned char *dest;
-       struct ethhdr *eth;
        u16 vid = 0;
 
        rcu_read_lock();
@@ -54,15 +53,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        BR_INPUT_SKB_CB(skb)->frag_max_size = 0;
 
        skb_reset_mac_header(skb);
-       eth = eth_hdr(skb);
        skb_pull(skb, ETH_HLEN);
 
        if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid, &state))
                goto out;
 
        if (IS_ENABLED(CONFIG_INET) &&
-           (eth->h_proto == htons(ETH_P_ARP) ||
-            eth->h_proto == htons(ETH_P_RARP)) &&
+           (eth_hdr(skb)->h_proto == htons(ETH_P_ARP) ||
+            eth_hdr(skb)->h_proto == htons(ETH_P_RARP)) &&
            br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
                br_do_proxy_suppress_arp(skb, br, vid, NULL);
        } else if (IS_ENABLED(CONFIG_IPV6) &&
index 6856a6d9282b830fce00cce256d671c17c08638f..1f14b84553457053479d2019f2ec9d8e6e2c41b1 100644 (file)
@@ -63,7 +63,8 @@ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
 {
        struct net_bridge_port *p;
 
-       list_for_each_entry_rcu(p, &br->port_list, list) {
+       list_for_each_entry_rcu(p, &br->port_list, list,
+                               lockdep_is_held(&br->lock)) {
                if (p->port_no == port_no)
                        return p;
        }
index a6316b336128cdb31eea6e80f1a47620abbd0d31..c6c985fe7b1bcf784cedde2b2a86e26356471bee 100644 (file)
 #include "net-sysfs.h"
 
 #define MAX_GRO_SKBS 8
-#define MAX_NEST_DEV 8
 
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
@@ -331,6 +330,12 @@ int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
        name_node = netdev_name_node_lookup(net, name);
        if (!name_node)
                return -ENOENT;
+       /* lookup might have found our primary name or a name belonging
+        * to another device.
+        */
+       if (name_node == dev->name_node || name_node->dev != dev)
+               return -EINVAL;
+
        __netdev_name_node_alt_destroy(name_node);
 
        return 0;
@@ -3071,6 +3076,8 @@ static u16 skb_tx_hash(const struct net_device *dev,
 
        if (skb_rx_queue_recorded(skb)) {
                hash = skb_get_rx_queue(skb);
+               if (hash >= qoffset)
+                       hash -= qoffset;
                while (unlikely(hash >= qcount))
                        hash -= qcount;
                return hash + qoffset;
@@ -3657,26 +3664,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
        qdisc_calculate_pkt_len(skb, q);
 
        if (q->flags & TCQ_F_NOLOCK) {
-               if ((q->flags & TCQ_F_CAN_BYPASS) && READ_ONCE(q->empty) &&
-                   qdisc_run_begin(q)) {
-                       if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED,
-                                             &q->state))) {
-                               __qdisc_drop(skb, &to_free);
-                               rc = NET_XMIT_DROP;
-                               goto end_run;
-                       }
-                       qdisc_bstats_cpu_update(q, skb);
-
-                       rc = NET_XMIT_SUCCESS;
-                       if (sch_direct_xmit(skb, q, dev, txq, NULL, true))
-                               __qdisc_run(q);
-
-end_run:
-                       qdisc_run_end(q);
-               } else {
-                       rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
-                       qdisc_run(q);
-               }
+               rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
+               qdisc_run(q);
 
                if (unlikely(to_free))
                        kfree_skb_list(to_free);
@@ -7201,8 +7190,8 @@ static int __netdev_walk_all_lower_dev(struct net_device *dev,
        return 0;
 }
 
-static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
-                                                   struct list_head **iter)
+struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
+                                            struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
@@ -7214,6 +7203,7 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
 
        return lower->dev;
 }
+EXPORT_SYMBOL(netdev_next_lower_dev_rcu);
 
 static u8 __netdev_upper_depth(struct net_device *dev)
 {
index 549ee56b7a21b72a9d721c66f04c667db12b822a..5e220809844c81c539d5e7506bc4095bd9a48ff4 100644 (file)
@@ -2103,11 +2103,11 @@ err_action_values_put:
 
 static struct devlink_dpipe_table *
 devlink_dpipe_table_find(struct list_head *dpipe_tables,
-                        const char *table_name)
+                        const char *table_name, struct devlink *devlink)
 {
        struct devlink_dpipe_table *table;
-
-       list_for_each_entry_rcu(table, dpipe_tables, list) {
+       list_for_each_entry_rcu(table, dpipe_tables, list,
+                               lockdep_is_held(&devlink->lock)) {
                if (!strcmp(table->name, table_name))
                        return table;
        }
@@ -2226,7 +2226,7 @@ static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
 
        table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                return -EINVAL;
 
@@ -2382,7 +2382,7 @@ static int devlink_dpipe_table_counters_set(struct devlink *devlink,
        struct devlink_dpipe_table *table;
 
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                return -EINVAL;
 
@@ -6854,7 +6854,7 @@ bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
 
        rcu_read_lock();
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        enabled = false;
        if (table)
                enabled = table->counters_enabled;
@@ -6878,26 +6878,34 @@ int devlink_dpipe_table_register(struct devlink *devlink,
                                 void *priv, bool counter_control_extern)
 {
        struct devlink_dpipe_table *table;
-
-       if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
-               return -EEXIST;
+       int err = 0;
 
        if (WARN_ON(!table_ops->size_get))
                return -EINVAL;
 
+       mutex_lock(&devlink->lock);
+
+       if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
+                                    devlink)) {
+               err = -EEXIST;
+               goto unlock;
+       }
+
        table = kzalloc(sizeof(*table), GFP_KERNEL);
-       if (!table)
-               return -ENOMEM;
+       if (!table) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
        table->name = table_name;
        table->table_ops = table_ops;
        table->priv = priv;
        table->counter_control_extern = counter_control_extern;
 
-       mutex_lock(&devlink->lock);
        list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
+unlock:
        mutex_unlock(&devlink->lock);
-       return 0;
+       return err;
 }
 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
 
@@ -6914,7 +6922,7 @@ void devlink_dpipe_table_unregister(struct devlink *devlink,
 
        mutex_lock(&devlink->lock);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                goto unlock;
        list_del_rcu(&table->list);
@@ -7071,7 +7079,7 @@ int devlink_dpipe_table_resource_set(struct devlink *devlink,
 
        mutex_lock(&devlink->lock);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table) {
                err = -EINVAL;
                goto out;
index 3e7e15278c46847e9d6d25ad960d015fbaa8b6fa..bd7eba9066f8d6b39d04be38611535f238bf5cd0 100644 (file)
@@ -974,7 +974,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 
        frh = nlmsg_data(nlh);
        frh->family = ops->family;
-       frh->table = rule->table;
+       frh->table = rule->table < 256 ? rule->table : RT_TABLE_COMPAT;
        if (nla_put_u32(skb, FRA_TABLE, rule->table))
                goto nla_put_failure;
        if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen))
index 09c44bf2e1d28842d77b4ed442ef2c051a25ad21..e1152f4ffe33efb0a69f17a1f5940baa04942e5b 100644 (file)
@@ -3504,27 +3504,25 @@ static int rtnl_alt_ifname(int cmd, struct net_device *dev, struct nlattr *attr,
        if (err)
                return err;
 
-       alt_ifname = nla_data(attr);
+       alt_ifname = nla_strdup(attr, GFP_KERNEL);
+       if (!alt_ifname)
+               return -ENOMEM;
+
        if (cmd == RTM_NEWLINKPROP) {
-               alt_ifname = kstrdup(alt_ifname, GFP_KERNEL);
-               if (!alt_ifname)
-                       return -ENOMEM;
                err = netdev_name_node_alt_create(dev, alt_ifname);
-               if (err) {
-                       kfree(alt_ifname);
-                       return err;
-               }
+               if (!err)
+                       alt_ifname = NULL;
        } else if (cmd == RTM_DELLINKPROP) {
                err = netdev_name_node_alt_destroy(dev, alt_ifname);
-               if (err)
-                       return err;
        } else {
-               WARN_ON(1);
-               return 0;
+               WARN_ON_ONCE(1);
+               err = -EINVAL;
        }
 
-       *changed = true;
-       return 0;
+       kfree(alt_ifname);
+       if (!err)
+               *changed = true;
+       return err;
 }
 
 static int rtnl_linkprop(int cmd, struct sk_buff *skb, struct nlmsghdr *nlh,
index 864cb9e9622f539c14fdeeffd597a6b697e84d26..e1101a4f90a6353038fac59de8a193c91c7d8874 100644 (file)
@@ -467,7 +467,6 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
                return NULL;
        }
 
-       /* use OR instead of assignment to avoid clearing of bits in mask */
        if (pfmemalloc)
                skb->pfmemalloc = 1;
        skb->head_frag = 1;
@@ -527,7 +526,6 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
                return NULL;
        }
 
-       /* use OR instead of assignment to avoid clearing of bits in mask */
        if (nc->page.pfmemalloc)
                skb->pfmemalloc = 1;
        skb->head_frag = 1;
@@ -4805,9 +4803,9 @@ static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb,
                                      typeof(IPPROTO_IP) proto,
                                      unsigned int off)
 {
-       switch (proto) {
-               int err;
+       int err;
 
+       switch (proto) {
        case IPPROTO_TCP:
                err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr),
                                          off + MAX_TCP_HDR_LEN);
index fce45dac42056b26a61ca71d527dfb70e3d16b33..ef9197541cb3ba4eadb65aa453df0d29a07747b2 100644 (file)
@@ -305,7 +305,8 @@ nla_put_failure:
 static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
        [ETHTOOL_A_BITSET_UNSPEC]       = { .type = NLA_REJECT },
        [ETHTOOL_A_BITSET_NOMASK]       = { .type = NLA_FLAG },
-       [ETHTOOL_A_BITSET_SIZE]         = { .type = NLA_U32 },
+       [ETHTOOL_A_BITSET_SIZE]         = NLA_POLICY_MAX(NLA_U32,
+                                                        ETHNL_MAX_BITSET_SIZE),
        [ETHTOOL_A_BITSET_BITS]         = { .type = NLA_NESTED },
        [ETHTOOL_A_BITSET_VALUE]        = { .type = NLA_BINARY },
        [ETHTOOL_A_BITSET_MASK]         = { .type = NLA_BINARY },
@@ -447,7 +448,10 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
                                    "mask only allowed in compact bitset");
                return -EINVAL;
        }
+
        no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
+       if (no_mask)
+               ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
 
        nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
                bool old_val, new_val;
index b8247e34109d0272a96dd3e261b9da473f0a306b..b849f9d1967699c017a1b3e201f4a2b1e33c166c 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef _NET_ETHTOOL_BITSET_H
 #define _NET_ETHTOOL_BITSET_H
 
+#define ETHNL_MAX_BITSET_SIZE S16_MAX
+
 typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN];
 
 int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact);
index 364ea2cc028e9a0ccb1a9d409961943cae8e1b3f..3ba7f61be10784a6bb5c814dfe669c320edbc8dd 100644 (file)
@@ -155,7 +155,8 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
                new_node->seq_out[i] = seq_out;
 
        spin_lock_bh(&hsr->list_lock);
-       list_for_each_entry_rcu(node, node_db, mac_list) {
+       list_for_each_entry_rcu(node, node_db, mac_list,
+                               lockdep_is_held(&hsr->list_lock)) {
                if (ether_addr_equal(node->macaddress_A, addr))
                        goto out;
                if (ether_addr_equal(node->macaddress_B, addr))
index 3768822159192b919f33e8174003369ca235cde1..0bd10a1f477fdfd6bdc8b6c4a14f132280faedcf 100644 (file)
@@ -1724,6 +1724,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 {
        unsigned char optbuf[sizeof(struct ip_options) + 40];
        struct ip_options *opt = (struct ip_options *)optbuf;
+       int res;
 
        if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
                return;
@@ -1735,7 +1736,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 
        memset(opt, 0, sizeof(struct ip_options));
        opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr);
-       if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL))
+       rcu_read_lock();
+       res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL);
+       rcu_read_unlock();
+
+       if (res)
                return;
 
        if (gateway)
index 316ebdf8151d6e836fcd68e6063ab3302fae779a..6b6b57000dad879996310717eeb016d2aad46541 100644 (file)
@@ -6124,7 +6124,11 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
 {
        struct request_sock *req;
 
-       tcp_try_undo_loss(sk, false);
+       /* If we are still handling the SYNACK RTO, see if timestamp ECR allows
+        * undo. If peer SACKs triggered fast recovery, we can't undo here.
+        */
+       if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
+               tcp_try_undo_loss(sk, false);
 
        /* Reset rtx states to prevent spurious retransmits_timed_out() */
        tcp_sk(sk)->retrans_stamp = 0;
index db76b96092991cb3f0057035e0e051141511acd5..08a41f1e1cd22478b9ea7740fa34e3979373ac6f 100644 (file)
@@ -1857,8 +1857,12 @@ int __udp_disconnect(struct sock *sk, int flags)
        inet->inet_dport = 0;
        sock_rps_reset_rxhash(sk);
        sk->sk_bound_dev_if = 0;
-       if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
+       if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) {
                inet_reset_saddr(sk);
+               if (sk->sk_prot->rehash &&
+                   (sk->sk_userlocks & SOCK_BINDPORT_LOCK))
+                       sk->sk_prot->rehash(sk);
+       }
 
        if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) {
                sk->sk_prot->unhash(sk);
index 58fbde24438116950c11e7cf8e0ca6f59fec23d9..72abf892302f27fd50179b1b5b6d6e0f974a06b9 100644 (file)
@@ -1102,8 +1102,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
                                        found++;
                                        break;
                                }
-                               if (rt_can_ecmp)
-                                       fallback_ins = fallback_ins ?: ins;
+                               fallback_ins = fallback_ins ?: ins;
                                goto next_iter;
                        }
 
@@ -1146,7 +1145,9 @@ next_iter:
        }
 
        if (fallback_ins && !found) {
-               /* No ECMP-able route found, replace first non-ECMP one */
+               /* No matching route with same ecmp-able-ness found, replace
+                * first matching route
+                */
                ins = fallback_ins;
                iter = rcu_dereference_protected(*ins,
                                    lockdep_is_held(&rt->fib6_table->tb6_lock));
index 55bfc5149d0c5b5a6063dbdf19c2055a3b9aea93..781ca8c07a0da3619d31f8ddd06c8ae69a7a17eb 100644 (file)
@@ -437,8 +437,6 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return -ENOENT;
 
        switch (type) {
-               struct ipv6_tlv_tnl_enc_lim *tel;
-               __u32 teli;
        case ICMPV6_DEST_UNREACH:
                net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
                                    t->parms.name);
@@ -452,7 +450,10 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        break;
                }
                return 0;
-       case ICMPV6_PARAMPROB:
+       case ICMPV6_PARAMPROB: {
+               struct ipv6_tlv_tnl_enc_lim *tel;
+               __u32 teli;
+
                teli = 0;
                if (code == ICMPV6_HDR_FIELD)
                        teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data);
@@ -468,6 +469,7 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                                            t->parms.name);
                }
                return 0;
+       }
        case ICMPV6_PKT_TOOBIG:
                ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
                return 0;
index 5d65436ad5adfa64174dc542ef001b069608ed7f..4703b09808d0af016ae566a5be5cb490c7179d38 100644 (file)
@@ -517,8 +517,6 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
        err = 0;
 
        switch (*type) {
-               struct ipv6_tlv_tnl_enc_lim *tel;
-               __u32 mtu, teli;
        case ICMPV6_DEST_UNREACH:
                net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
                                    t->parms.name);
@@ -531,7 +529,10 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                        rel_msg = 1;
                }
                break;
-       case ICMPV6_PARAMPROB:
+       case ICMPV6_PARAMPROB: {
+               struct ipv6_tlv_tnl_enc_lim *tel;
+               __u32 teli;
+
                teli = 0;
                if ((*code) == ICMPV6_HDR_FIELD)
                        teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data);
@@ -548,7 +549,10 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                                            t->parms.name);
                }
                break;
-       case ICMPV6_PKT_TOOBIG:
+       }
+       case ICMPV6_PKT_TOOBIG: {
+               __u32 mtu;
+
                ip6_update_pmtu(skb, net, htonl(*info), 0, 0,
                                sock_net_uid(net, NULL));
                mtu = *info - offset;
@@ -562,6 +566,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                        rel_msg = 1;
                }
                break;
+       }
        case NDISC_REDIRECT:
                ip6_redirect(skb, net, skb->dev->ifindex, 0,
                             sock_net_uid(net, NULL));
index 79fc012dd2cae44b69057c168037b018775d1f49..debdaeba5d8c130dbf7dd099bc29fbed80a7ac75 100644 (file)
@@ -183,9 +183,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                                        retv = -EBUSY;
                                        break;
                                }
-                       } else if (sk->sk_protocol != IPPROTO_TCP)
+                       } else if (sk->sk_protocol == IPPROTO_TCP) {
+                               if (sk->sk_prot != &tcpv6_prot) {
+                                       retv = -EBUSY;
+                                       break;
+                               }
                                break;
-
+                       } else {
+                               break;
+                       }
                        if (sk->sk_state != TCP_ESTABLISHED) {
                                retv = -ENOTCONN;
                                break;
index 4fbdc60b4e070802fcd6905dce800641816a79fa..2931224b674e81e1608cbf5b6a08a31cb6f99415 100644 (file)
@@ -5198,6 +5198,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
                 */
                cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL |
                                                     NLM_F_REPLACE);
+               cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE;
                nhn++;
        }
 
index e041af2f021ad68c5c001931c5bf4a8def849a57..88d7a692a9658137f06128c7a7c98b2a358d12b2 100644 (file)
@@ -2959,7 +2959,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
            (auth_transaction == 2 &&
             ifmgd->auth_data->expected_transaction == 2)) {
                if (!ieee80211_mark_sta_auth(sdata, bssid))
-                       goto out_err;
+                       return; /* ignore frame -- wait for timeout */
        } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
                   auth_transaction == 2) {
                sdata_info(sdata, "SAE peer confirmed\n");
@@ -2967,10 +2967,6 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        }
 
        cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
-       return;
- out_err:
-       mutex_unlock(&sdata->local->sta_mtx);
-       /* ignore frame -- wait for timeout */
 }
 
 #define case_WLAN(type) \
index 0e05ff0376726ddbaf80f05d9f90f6f086225b88..0ba98ad9bc854800fad0c90cc594bc6d98b12508 100644 (file)
@@ -4114,7 +4114,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
 
        lockdep_assert_held(&local->sta_mtx);
 
-       list_for_each_entry_rcu(sta, &local->sta_list, list) {
+       list_for_each_entry(sta, &local->sta_list, list) {
                if (sdata != sta->sdata &&
                    (!sta->sdata->bss || sta->sdata->bss != sdata->bss))
                        continue;
index 49f6054e7f4ebc15837ad7f0c61420063ea00104..a9ed3bf1d93faaf6ca3f2597e2bde6ff3a5f3487 100644 (file)
@@ -4,6 +4,7 @@ config MPTCP
        depends on INET
        select SKB_EXTENSIONS
        select CRYPTO_LIB_SHA256
+       select CRYPTO
        help
          Multipath TCP (MPTCP) connections send and receive data over multiple
          subflows in order to utilize multiple network paths. Each subflow
index 030dee668e0a3cd2390f28aed620f0ab76a5d425..3c19a8efdceadcde707150a33bc03c31dc8a0b84 100644 (file)
@@ -543,6 +543,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
        }
 }
 
+static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu)
+{
+       return 0;
+}
+
 static int __mptcp_init_sock(struct sock *sk)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
@@ -551,6 +556,7 @@ static int __mptcp_init_sock(struct sock *sk)
        __set_bit(MPTCP_SEND_SPACE, &msk->flags);
 
        msk->first = NULL;
+       inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
 
        return 0;
 }
@@ -755,60 +761,50 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
                            char __user *optval, unsigned int optlen)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
-       int ret = -EOPNOTSUPP;
        struct socket *ssock;
-       struct sock *ssk;
 
        pr_debug("msk=%p", msk);
 
        /* @@ the meaning of setsockopt() when the socket is connected and
-        * there are multiple subflows is not defined.
+        * there are multiple subflows is not yet defined. It is up to the
+        * MPTCP-level socket to configure the subflows until the subflow
+        * is in TCP fallback, when TCP socket options are passed through
+        * to the one remaining subflow.
         */
        lock_sock(sk);
-       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
-       if (IS_ERR(ssock)) {
-               release_sock(sk);
-               return ret;
-       }
+       ssock = __mptcp_tcp_fallback(msk);
+       if (ssock)
+               return tcp_setsockopt(ssock->sk, level, optname, optval,
+                                     optlen);
 
-       ssk = ssock->sk;
-       sock_hold(ssk);
        release_sock(sk);
 
-       ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
-       sock_put(ssk);
-
-       return ret;
+       return -EOPNOTSUPP;
 }
 
 static int mptcp_getsockopt(struct sock *sk, int level, int optname,
                            char __user *optval, int __user *option)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
-       int ret = -EOPNOTSUPP;
        struct socket *ssock;
-       struct sock *ssk;
 
        pr_debug("msk=%p", msk);
 
-       /* @@ the meaning of getsockopt() when the socket is connected and
-        * there are multiple subflows is not defined.
+       /* @@ the meaning of setsockopt() when the socket is connected and
+        * there are multiple subflows is not yet defined. It is up to the
+        * MPTCP-level socket to configure the subflows until the subflow
+        * is in TCP fallback, when socket options are passed through
+        * to the one remaining subflow.
         */
        lock_sock(sk);
-       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
-       if (IS_ERR(ssock)) {
-               release_sock(sk);
-               return ret;
-       }
+       ssock = __mptcp_tcp_fallback(msk);
+       if (ssock)
+               return tcp_getsockopt(ssock->sk, level, optname, optval,
+                                     option);
 
-       ssk = ssock->sk;
-       sock_hold(ssk);
        release_sock(sk);
 
-       ret = tcp_getsockopt(ssk, level, optname, optval, option);
-       sock_put(ssk);
-
-       return ret;
+       return -EOPNOTSUPP;
 }
 
 static int mptcp_get_port(struct sock *sk, unsigned short snum)
index 8a99a29302846fdc2b21d225daffa7e44adb067c..9f8663b30456256bfdd0e8e4d89061bc90e5281a 100644 (file)
@@ -56,8 +56,8 @@
 #define MPTCP_DSS_FLAG_MASK    (0x1F)
 
 /* MPTCP socket flags */
-#define MPTCP_DATA_READY       BIT(0)
-#define MPTCP_SEND_SPACE       BIT(1)
+#define MPTCP_DATA_READY       0
+#define MPTCP_SEND_SPACE       1
 
 /* MPTCP connection sock */
 struct mptcp_sock {
index 69c107f9ba8db06ebb0b332a7fb91e2514d5831e..8dd17589217d71e4e38f6d442434130cadd290e0 100644 (file)
@@ -723,6 +723,20 @@ ip_set_rcu_get(struct net *net, ip_set_id_t index)
        return set;
 }
 
+static inline void
+ip_set_lock(struct ip_set *set)
+{
+       if (!set->variant->region_lock)
+               spin_lock_bh(&set->lock);
+}
+
+static inline void
+ip_set_unlock(struct ip_set *set)
+{
+       if (!set->variant->region_lock)
+               spin_unlock_bh(&set->lock);
+}
+
 int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
            const struct xt_action_param *par, struct ip_set_adt_opt *opt)
@@ -744,9 +758,9 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
        if (ret == -EAGAIN) {
                /* Type requests element to be completed */
                pr_debug("element must be completed, ADD is triggered\n");
-               spin_lock_bh(&set->lock);
+               ip_set_lock(set);
                set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-               spin_unlock_bh(&set->lock);
+               ip_set_unlock(set);
                ret = 1;
        } else {
                /* --return-nomatch: invert matched element */
@@ -775,9 +789,9 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 
        return ret;
 }
@@ -797,9 +811,9 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 
        return ret;
 }
@@ -1264,9 +1278,9 @@ ip_set_flush_set(struct ip_set *set)
 {
        pr_debug("set: %s\n",  set->name);
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        set->variant->flush(set);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 }
 
 static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb,
@@ -1713,9 +1727,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
        bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
 
        do {
-               spin_lock_bh(&set->lock);
+               ip_set_lock(set);
                ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
-               spin_unlock_bh(&set->lock);
+               ip_set_unlock(set);
                retried = true;
        } while (ret == -EAGAIN &&
                 set->variant->resize &&
index 7480ce55b5c856feba27bc47341ff8158068e11f..e52d7b7597a0d8f3d6cfed5d2af6544ae1ad2e5d 100644 (file)
@@ -7,13 +7,21 @@
 #include <linux/rcupdate.h>
 #include <linux/jhash.h>
 #include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/ipset/ip_set.h>
 
-#define __ipset_dereference_protected(p, c)    rcu_dereference_protected(p, c)
-#define ipset_dereference_protected(p, set) \
-       __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock))
-
-#define rcu_dereference_bh_nfnl(p)     rcu_dereference_bh_check(p, 1)
+#define __ipset_dereference(p)         \
+       rcu_dereference_protected(p, 1)
+#define ipset_dereference_nfnl(p)      \
+       rcu_dereference_protected(p,    \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
+#define ipset_dereference_set(p, set)  \
+       rcu_dereference_protected(p,    \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
+               lockdep_is_held(&(set)->lock))
+#define ipset_dereference_bh_nfnl(p)   \
+       rcu_dereference_bh_check(p,     \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
 
 /* Hashing which uses arrays to resolve clashing. The hash table is resized
  * (doubled) when searching becomes too long.
@@ -72,11 +80,35 @@ struct hbucket {
                __aligned(__alignof__(u64));
 };
 
+/* Region size for locking == 2^HTABLE_REGION_BITS */
+#define HTABLE_REGION_BITS     10
+#define ahash_numof_locks(htable_bits)         \
+       ((htable_bits) < HTABLE_REGION_BITS ? 1 \
+               : jhash_size((htable_bits) - HTABLE_REGION_BITS))
+#define ahash_sizeof_regions(htable_bits)              \
+       (ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region))
+#define ahash_region(n, htable_bits)           \
+       ((n) % ahash_numof_locks(htable_bits))
+#define ahash_bucket_start(h,  htable_bits)    \
+       ((htable_bits) < HTABLE_REGION_BITS ? 0 \
+               : (h) * jhash_size(HTABLE_REGION_BITS))
+#define ahash_bucket_end(h,  htable_bits)      \
+       ((htable_bits) < HTABLE_REGION_BITS ? jhash_size(htable_bits)   \
+               : ((h) + 1) * jhash_size(HTABLE_REGION_BITS))
+
+struct htable_gc {
+       struct delayed_work dwork;
+       struct ip_set *set;     /* Set the gc belongs to */
+       u32 region;             /* Last gc run position */
+};
+
 /* The hash table: the table size stored here in order to make resizing easy */
 struct htable {
        atomic_t ref;           /* References for resizing */
-       atomic_t uref;          /* References for dumping */
+       atomic_t uref;          /* References for dumping and gc */
        u8 htable_bits;         /* size of hash table == 2^htable_bits */
+       u32 maxelem;            /* Maxelem per region */
+       struct ip_set_region *hregion;  /* Region locks and ext sizes */
        struct hbucket __rcu *bucket[0]; /* hashtable buckets */
 };
 
@@ -162,6 +194,10 @@ htable_bits(u32 hashsize)
 #define NLEN                   0
 #endif /* IP_SET_HASH_WITH_NETS */
 
+#define SET_ELEM_EXPIRED(set, d)       \
+       (SET_WITH_TIMEOUT(set) &&       \
+        ip_set_timeout_expired(ext_timeout(d, set)))
+
 #endif /* _IP_SET_HASH_GEN_H */
 
 #ifndef MTYPE
@@ -205,10 +241,12 @@ htable_bits(u32 hashsize)
 #undef mtype_test_cidrs
 #undef mtype_test
 #undef mtype_uref
-#undef mtype_expire
 #undef mtype_resize
+#undef mtype_ext_size
+#undef mtype_resize_ad
 #undef mtype_head
 #undef mtype_list
+#undef mtype_gc_do
 #undef mtype_gc
 #undef mtype_gc_init
 #undef mtype_variant
@@ -247,10 +285,12 @@ htable_bits(u32 hashsize)
 #define mtype_test_cidrs       IPSET_TOKEN(MTYPE, _test_cidrs)
 #define mtype_test             IPSET_TOKEN(MTYPE, _test)
 #define mtype_uref             IPSET_TOKEN(MTYPE, _uref)
-#define mtype_expire           IPSET_TOKEN(MTYPE, _expire)
 #define mtype_resize           IPSET_TOKEN(MTYPE, _resize)
+#define mtype_ext_size         IPSET_TOKEN(MTYPE, _ext_size)
+#define mtype_resize_ad                IPSET_TOKEN(MTYPE, _resize_ad)
 #define mtype_head             IPSET_TOKEN(MTYPE, _head)
 #define mtype_list             IPSET_TOKEN(MTYPE, _list)
+#define mtype_gc_do            IPSET_TOKEN(MTYPE, _gc_do)
 #define mtype_gc               IPSET_TOKEN(MTYPE, _gc)
 #define mtype_gc_init          IPSET_TOKEN(MTYPE, _gc_init)
 #define mtype_variant          IPSET_TOKEN(MTYPE, _variant)
@@ -275,8 +315,7 @@ htable_bits(u32 hashsize)
 /* The generic hash structure */
 struct htype {
        struct htable __rcu *table; /* the hash table */
-       struct timer_list gc;   /* garbage collection when timeout enabled */
-       struct ip_set *set;     /* attached to this ip_set */
+       struct htable_gc gc;    /* gc workqueue */
        u32 maxelem;            /* max elements in the hash */
        u32 initval;            /* random jhash init value */
 #ifdef IP_SET_HASH_WITH_MARKMASK
@@ -288,21 +327,33 @@ struct htype {
 #ifdef IP_SET_HASH_WITH_NETMASK
        u8 netmask;             /* netmask value for subnets to store */
 #endif
+       struct list_head ad;    /* Resize add|del backlist */
        struct mtype_elem next; /* temporary storage for uadd */
 #ifdef IP_SET_HASH_WITH_NETS
        struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */
 #endif
 };
 
+/* ADD|DEL entries saved during resize */
+struct mtype_resize_ad {
+       struct list_head list;
+       enum ipset_adt ad;      /* ADD|DEL element */
+       struct mtype_elem d;    /* Element value */
+       struct ip_set_ext ext;  /* Extensions for ADD */
+       struct ip_set_ext mext; /* Target extensions for ADD */
+       u32 flags;              /* Flags for ADD */
+};
+
 #ifdef IP_SET_HASH_WITH_NETS
 /* Network cidr size book keeping when the hash stores different
  * sized networks. cidr == real cidr + 1 to support /0.
  */
 static void
-mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
 {
        int i, j;
 
+       spin_lock_bh(&set->lock);
        /* Add in increasing prefix order, so larger cidr first */
        for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) {
                if (j != -1) {
@@ -311,7 +362,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
                        j = i;
                } else if (h->nets[i].cidr[n] == cidr) {
                        h->nets[CIDR_POS(cidr)].nets[n]++;
-                       return;
+                       goto unlock;
                }
        }
        if (j != -1) {
@@ -320,24 +371,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
        }
        h->nets[i].cidr[n] = cidr;
        h->nets[CIDR_POS(cidr)].nets[n] = 1;
+unlock:
+       spin_unlock_bh(&set->lock);
 }
 
 static void
-mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
 {
        u8 i, j, net_end = NLEN - 1;
 
+       spin_lock_bh(&set->lock);
        for (i = 0; i < NLEN; i++) {
                if (h->nets[i].cidr[n] != cidr)
                        continue;
                h->nets[CIDR_POS(cidr)].nets[n]--;
                if (h->nets[CIDR_POS(cidr)].nets[n] > 0)
-                       return;
+                       goto unlock;
                for (j = i; j < net_end && h->nets[j].cidr[n]; j++)
                        h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
                h->nets[j].cidr[n] = 0;
-               return;
+               goto unlock;
        }
+unlock:
+       spin_unlock_bh(&set->lock);
 }
 #endif
 
@@ -345,7 +401,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
 static size_t
 mtype_ahash_memsize(const struct htype *h, const struct htable *t)
 {
-       return sizeof(*h) + sizeof(*t);
+       return sizeof(*h) + sizeof(*t) + ahash_sizeof_regions(t->htable_bits);
 }
 
 /* Get the ith element from the array block n */
@@ -369,24 +425,29 @@ mtype_flush(struct ip_set *set)
        struct htype *h = set->data;
        struct htable *t;
        struct hbucket *n;
-       u32 i;
-
-       t = ipset_dereference_protected(h->table, set);
-       for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
-               if (!n)
-                       continue;
-               if (set->extensions & IPSET_EXT_DESTROY)
-                       mtype_ext_cleanup(set, n);
-               /* FIXME: use slab cache */
-               rcu_assign_pointer(hbucket(t, i), NULL);
-               kfree_rcu(n, rcu);
+       u32 r, i;
+
+       t = ipset_dereference_nfnl(h->table);
+       for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+               spin_lock_bh(&t->hregion[r].lock);
+               for (i = ahash_bucket_start(r, t->htable_bits);
+                    i < ahash_bucket_end(r, t->htable_bits); i++) {
+                       n = __ipset_dereference(hbucket(t, i));
+                       if (!n)
+                               continue;
+                       if (set->extensions & IPSET_EXT_DESTROY)
+                               mtype_ext_cleanup(set, n);
+                       /* FIXME: use slab cache */
+                       rcu_assign_pointer(hbucket(t, i), NULL);
+                       kfree_rcu(n, rcu);
+               }
+               t->hregion[r].ext_size = 0;
+               t->hregion[r].elements = 0;
+               spin_unlock_bh(&t->hregion[r].lock);
        }
 #ifdef IP_SET_HASH_WITH_NETS
        memset(h->nets, 0, sizeof(h->nets));
 #endif
-       set->elements = 0;
-       set->ext_size = 0;
 }
 
 /* Destroy the hashtable part of the set */
@@ -397,7 +458,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
        u32 i;
 
        for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
+               n = __ipset_dereference(hbucket(t, i));
                if (!n)
                        continue;
                if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -406,6 +467,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
                kfree(n);
        }
 
+       ip_set_free(t->hregion);
        ip_set_free(t);
 }
 
@@ -414,28 +476,21 @@ static void
 mtype_destroy(struct ip_set *set)
 {
        struct htype *h = set->data;
+       struct list_head *l, *lt;
 
        if (SET_WITH_TIMEOUT(set))
-               del_timer_sync(&h->gc);
+               cancel_delayed_work_sync(&h->gc.dwork);
 
-       mtype_ahash_destroy(set,
-                           __ipset_dereference_protected(h->table, 1), true);
+       mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
+       list_for_each_safe(l, lt, &h->ad) {
+               list_del(l);
+               kfree(l);
+       }
        kfree(h);
 
        set->data = NULL;
 }
 
-static void
-mtype_gc_init(struct ip_set *set, void (*gc)(struct timer_list *t))
-{
-       struct htype *h = set->data;
-
-       timer_setup(&h->gc, gc, 0);
-       mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
-       pr_debug("gc initialized, run in every %u\n",
-                IPSET_GC_PERIOD(set->timeout));
-}
-
 static bool
 mtype_same_set(const struct ip_set *a, const struct ip_set *b)
 {
@@ -454,11 +509,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
               a->extensions == b->extensions;
 }
 
-/* Delete expired elements from the hashtable */
 static void
-mtype_expire(struct ip_set *set, struct htype *h)
+mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r)
 {
-       struct htable *t;
        struct hbucket *n, *tmp;
        struct mtype_elem *data;
        u32 i, j, d;
@@ -466,10 +519,12 @@ mtype_expire(struct ip_set *set, struct htype *h)
 #ifdef IP_SET_HASH_WITH_NETS
        u8 k;
 #endif
+       u8 htable_bits = t->htable_bits;
 
-       t = ipset_dereference_protected(h->table, set);
-       for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
+       spin_lock_bh(&t->hregion[r].lock);
+       for (i = ahash_bucket_start(r, htable_bits);
+            i < ahash_bucket_end(r, htable_bits); i++) {
+               n = __ipset_dereference(hbucket(t, i));
                if (!n)
                        continue;
                for (j = 0, d = 0; j < n->pos; j++) {
@@ -485,58 +540,100 @@ mtype_expire(struct ip_set *set, struct htype *h)
                        smp_mb__after_atomic();
 #ifdef IP_SET_HASH_WITH_NETS
                        for (k = 0; k < IPSET_NET_COUNT; k++)
-                               mtype_del_cidr(h,
+                               mtype_del_cidr(set, h,
                                        NCIDR_PUT(DCIDR_GET(data->cidr, k)),
                                        k);
 #endif
+                       t->hregion[r].elements--;
                        ip_set_ext_destroy(set, data);
-                       set->elements--;
                        d++;
                }
                if (d >= AHASH_INIT_SIZE) {
                        if (d >= n->size) {
+                               t->hregion[r].ext_size -=
+                                       ext_size(n->size, dsize);
                                rcu_assign_pointer(hbucket(t, i), NULL);
                                kfree_rcu(n, rcu);
                                continue;
                        }
                        tmp = kzalloc(sizeof(*tmp) +
-                                     (n->size - AHASH_INIT_SIZE) * dsize,
-                                     GFP_ATOMIC);
+                               (n->size - AHASH_INIT_SIZE) * dsize,
+                               GFP_ATOMIC);
                        if (!tmp)
-                               /* Still try to delete expired elements */
+                               /* Still try to delete expired elements. */
                                continue;
                        tmp->size = n->size - AHASH_INIT_SIZE;
                        for (j = 0, d = 0; j < n->pos; j++) {
                                if (!test_bit(j, n->used))
                                        continue;
                                data = ahash_data(n, j, dsize);
-                               memcpy(tmp->value + d * dsize, data, dsize);
+                               memcpy(tmp->value + d * dsize,
+                                      data, dsize);
                                set_bit(d, tmp->used);
                                d++;
                        }
                        tmp->pos = d;
-                       set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+                       t->hregion[r].ext_size -=
+                               ext_size(AHASH_INIT_SIZE, dsize);
                        rcu_assign_pointer(hbucket(t, i), tmp);
                        kfree_rcu(n, rcu);
                }
        }
+       spin_unlock_bh(&t->hregion[r].lock);
 }
 
 static void
-mtype_gc(struct timer_list *t)
+mtype_gc(struct work_struct *work)
 {
-       struct htype *h = from_timer(h, t, gc);
-       struct ip_set *set = h->set;
+       struct htable_gc *gc;
+       struct ip_set *set;
+       struct htype *h;
+       struct htable *t;
+       u32 r, numof_locks;
+       unsigned int next_run;
+
+       gc = container_of(work, struct htable_gc, dwork.work);
+       set = gc->set;
+       h = set->data;
 
-       pr_debug("called\n");
        spin_lock_bh(&set->lock);
-       mtype_expire(set, h);
+       t = ipset_dereference_set(h->table, set);
+       atomic_inc(&t->uref);
+       numof_locks = ahash_numof_locks(t->htable_bits);
+       r = gc->region++;
+       if (r >= numof_locks) {
+               r = gc->region = 0;
+       }
+       next_run = (IPSET_GC_PERIOD(set->timeout) * HZ) / numof_locks;
+       if (next_run < HZ/10)
+               next_run = HZ/10;
        spin_unlock_bh(&set->lock);
 
-       h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
-       add_timer(&h->gc);
+       mtype_gc_do(set, h, t, r);
+
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by expire: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
+
+       queue_delayed_work(system_power_efficient_wq, &gc->dwork, next_run);
+
+}
+
+static void
+mtype_gc_init(struct htable_gc *gc)
+{
+       INIT_DEFERRABLE_WORK(&gc->dwork, mtype_gc);
+       queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ);
 }
 
+static int
+mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+         struct ip_set_ext *mext, u32 flags);
+static int
+mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+         struct ip_set_ext *mext, u32 flags);
+
 /* Resize a hash: create a new hash table with doubling the hashsize
  * and inserting the elements to it. Repeat until we succeed or
  * fail due to memory pressures.
@@ -547,7 +644,7 @@ mtype_resize(struct ip_set *set, bool retried)
        struct htype *h = set->data;
        struct htable *t, *orig;
        u8 htable_bits;
-       size_t extsize, dsize = set->dsize;
+       size_t dsize = set->dsize;
 #ifdef IP_SET_HASH_WITH_NETS
        u8 flags;
        struct mtype_elem *tmp;
@@ -555,7 +652,9 @@ mtype_resize(struct ip_set *set, bool retried)
        struct mtype_elem *data;
        struct mtype_elem *d;
        struct hbucket *n, *m;
-       u32 i, j, key;
+       struct list_head *l, *lt;
+       struct mtype_resize_ad *x;
+       u32 i, j, r, nr, key;
        int ret;
 
 #ifdef IP_SET_HASH_WITH_NETS
@@ -563,10 +662,8 @@ mtype_resize(struct ip_set *set, bool retried)
        if (!tmp)
                return -ENOMEM;
 #endif
-       rcu_read_lock_bh();
-       orig = rcu_dereference_bh_nfnl(h->table);
+       orig = ipset_dereference_bh_nfnl(h->table);
        htable_bits = orig->htable_bits;
-       rcu_read_unlock_bh();
 
 retry:
        ret = 0;
@@ -583,88 +680,124 @@ retry:
                ret = -ENOMEM;
                goto out;
        }
+       t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits));
+       if (!t->hregion) {
+               kfree(t);
+               ret = -ENOMEM;
+               goto out;
+       }
        t->htable_bits = htable_bits;
+       t->maxelem = h->maxelem / ahash_numof_locks(htable_bits);
+       for (i = 0; i < ahash_numof_locks(htable_bits); i++)
+               spin_lock_init(&t->hregion[i].lock);
 
-       spin_lock_bh(&set->lock);
-       orig = __ipset_dereference_protected(h->table, 1);
-       /* There can't be another parallel resizing, but dumping is possible */
+       /* There can't be another parallel resizing,
+        * but dumping, gc, kernel side add/del are possible
+        */
+       orig = ipset_dereference_bh_nfnl(h->table);
        atomic_set(&orig->ref, 1);
        atomic_inc(&orig->uref);
-       extsize = 0;
        pr_debug("attempt to resize set %s from %u to %u, t %p\n",
                 set->name, orig->htable_bits, htable_bits, orig);
-       for (i = 0; i < jhash_size(orig->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(orig, i), 1);
-               if (!n)
-                       continue;
-               for (j = 0; j < n->pos; j++) {
-                       if (!test_bit(j, n->used))
+       for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) {
+               /* Expire may replace a hbucket with another one */
+               rcu_read_lock_bh();
+               for (i = ahash_bucket_start(r, orig->htable_bits);
+                    i < ahash_bucket_end(r, orig->htable_bits); i++) {
+                       n = __ipset_dereference(hbucket(orig, i));
+                       if (!n)
                                continue;
-                       data = ahash_data(n, j, dsize);
+                       for (j = 0; j < n->pos; j++) {
+                               if (!test_bit(j, n->used))
+                                       continue;
+                               data = ahash_data(n, j, dsize);
+                               if (SET_ELEM_EXPIRED(set, data))
+                                       continue;
 #ifdef IP_SET_HASH_WITH_NETS
-                       /* We have readers running parallel with us,
-                        * so the live data cannot be modified.
-                        */
-                       flags = 0;
-                       memcpy(tmp, data, dsize);
-                       data = tmp;
-                       mtype_data_reset_flags(data, &flags);
+                               /* We have readers running parallel with us,
+                                * so the live data cannot be modified.
+                                */
+                               flags = 0;
+                               memcpy(tmp, data, dsize);
+                               data = tmp;
+                               mtype_data_reset_flags(data, &flags);
 #endif
-                       key = HKEY(data, h->initval, htable_bits);
-                       m = __ipset_dereference_protected(hbucket(t, key), 1);
-                       if (!m) {
-                               m = kzalloc(sizeof(*m) +
+                               key = HKEY(data, h->initval, htable_bits);
+                               m = __ipset_dereference(hbucket(t, key));
+                               nr = ahash_region(key, htable_bits);
+                               if (!m) {
+                                       m = kzalloc(sizeof(*m) +
                                            AHASH_INIT_SIZE * dsize,
                                            GFP_ATOMIC);
-                               if (!m) {
-                                       ret = -ENOMEM;
-                                       goto cleanup;
-                               }
-                               m->size = AHASH_INIT_SIZE;
-                               extsize += ext_size(AHASH_INIT_SIZE, dsize);
-                               RCU_INIT_POINTER(hbucket(t, key), m);
-                       } else if (m->pos >= m->size) {
-                               struct hbucket *ht;
-
-                               if (m->size >= AHASH_MAX(h)) {
-                                       ret = -EAGAIN;
-                               } else {
-                                       ht = kzalloc(sizeof(*ht) +
+                                       if (!m) {
+                                               ret = -ENOMEM;
+                                               goto cleanup;
+                                       }
+                                       m->size = AHASH_INIT_SIZE;
+                                       t->hregion[nr].ext_size +=
+                                               ext_size(AHASH_INIT_SIZE,
+                                                        dsize);
+                                       RCU_INIT_POINTER(hbucket(t, key), m);
+                               } else if (m->pos >= m->size) {
+                                       struct hbucket *ht;
+
+                                       if (m->size >= AHASH_MAX(h)) {
+                                               ret = -EAGAIN;
+                                       } else {
+                                               ht = kzalloc(sizeof(*ht) +
                                                (m->size + AHASH_INIT_SIZE)
                                                * dsize,
                                                GFP_ATOMIC);
-                                       if (!ht)
-                                               ret = -ENOMEM;
+                                               if (!ht)
+                                                       ret = -ENOMEM;
+                                       }
+                                       if (ret < 0)
+                                               goto cleanup;
+                                       memcpy(ht, m, sizeof(struct hbucket) +
+                                              m->size * dsize);
+                                       ht->size = m->size + AHASH_INIT_SIZE;
+                                       t->hregion[nr].ext_size +=
+                                               ext_size(AHASH_INIT_SIZE,
+                                                        dsize);
+                                       kfree(m);
+                                       m = ht;
+                                       RCU_INIT_POINTER(hbucket(t, key), ht);
                                }
-                               if (ret < 0)
-                                       goto cleanup;
-                               memcpy(ht, m, sizeof(struct hbucket) +
-                                             m->size * dsize);
-                               ht->size = m->size + AHASH_INIT_SIZE;
-                               extsize += ext_size(AHASH_INIT_SIZE, dsize);
-                               kfree(m);
-                               m = ht;
-                               RCU_INIT_POINTER(hbucket(t, key), ht);
-                       }
-                       d = ahash_data(m, m->pos, dsize);
-                       memcpy(d, data, dsize);
-                       set_bit(m->pos++, m->used);
+                               d = ahash_data(m, m->pos, dsize);
+                               memcpy(d, data, dsize);
+                               set_bit(m->pos++, m->used);
+                               t->hregion[nr].elements++;
 #ifdef IP_SET_HASH_WITH_NETS
-                       mtype_data_reset_flags(d, &flags);
+                               mtype_data_reset_flags(d, &flags);
 #endif
+                       }
                }
+               rcu_read_unlock_bh();
        }
-       rcu_assign_pointer(h->table, t);
-       set->ext_size = extsize;
 
-       spin_unlock_bh(&set->lock);
+       /* There can't be any other writer. */
+       rcu_assign_pointer(h->table, t);
 
        /* Give time to other readers of the set */
        synchronize_rcu();
 
        pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
                 orig->htable_bits, orig, t->htable_bits, t);
-       /* If there's nobody else dumping the table, destroy it */
+       /* Add/delete elements processed by the SET target during resize.
+        * Kernel-side add cannot trigger a resize and userspace actions
+        * are serialized by the mutex.
+        */
+       list_for_each_safe(l, lt, &h->ad) {
+               x = list_entry(l, struct mtype_resize_ad, list);
+               if (x->ad == IPSET_ADD) {
+                       mtype_add(set, &x->d, &x->ext, &x->mext, x->flags);
+               } else {
+                       mtype_del(set, &x->d, NULL, NULL, 0);
+               }
+               list_del(l);
+               kfree(l);
+       }
+       /* If there's nobody else using the table, destroy it */
        if (atomic_dec_and_test(&orig->uref)) {
                pr_debug("Table destroy by resize %p\n", orig);
                mtype_ahash_destroy(set, orig, false);
@@ -677,15 +810,44 @@ out:
        return ret;
 
 cleanup:
+       rcu_read_unlock_bh();
        atomic_set(&orig->ref, 0);
        atomic_dec(&orig->uref);
-       spin_unlock_bh(&set->lock);
        mtype_ahash_destroy(set, t, false);
        if (ret == -EAGAIN)
                goto retry;
        goto out;
 }
 
+/* Get the current number of elements and ext_size in the set  */
+static void
+mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
+{
+       struct htype *h = set->data;
+       const struct htable *t;
+       u32 i, j, r;
+       struct hbucket *n;
+       struct mtype_elem *data;
+
+       t = rcu_dereference_bh(h->table);
+       for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+               for (i = ahash_bucket_start(r, t->htable_bits);
+                    i < ahash_bucket_end(r, t->htable_bits); i++) {
+                       n = rcu_dereference_bh(hbucket(t, i));
+                       if (!n)
+                               continue;
+                       for (j = 0; j < n->pos; j++) {
+                               if (!test_bit(j, n->used))
+                                       continue;
+                               data = ahash_data(n, j, set->dsize);
+                               if (!SET_ELEM_EXPIRED(set, data))
+                                       (*elements)++;
+                       }
+               }
+               *ext_size += t->hregion[r].ext_size;
+       }
+}
+
 /* Add an element to a hash and update the internal counters when succeeded,
  * otherwise report the proper error code.
  */
@@ -698,32 +860,49 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        const struct mtype_elem *d = value;
        struct mtype_elem *data;
        struct hbucket *n, *old = ERR_PTR(-ENOENT);
-       int i, j = -1;
+       int i, j = -1, ret;
        bool flag_exist = flags & IPSET_FLAG_EXIST;
        bool deleted = false, forceadd = false, reuse = false;
-       u32 key, multi = 0;
+       u32 r, key, multi = 0, elements, maxelem;
 
-       if (set->elements >= h->maxelem) {
-               if (SET_WITH_TIMEOUT(set))
-                       /* FIXME: when set is full, we slow down here */
-                       mtype_expire(set, h);
-               if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set))
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       key = HKEY(value, h->initval, t->htable_bits);
+       r = ahash_region(key, t->htable_bits);
+       atomic_inc(&t->uref);
+       elements = t->hregion[r].elements;
+       maxelem = t->maxelem;
+       if (elements >= maxelem) {
+               u32 e;
+               if (SET_WITH_TIMEOUT(set)) {
+                       rcu_read_unlock_bh();
+                       mtype_gc_do(set, h, t, r);
+                       rcu_read_lock_bh();
+               }
+               maxelem = h->maxelem;
+               elements = 0;
+               for (e = 0; e < ahash_numof_locks(t->htable_bits); e++)
+                       elements += t->hregion[e].elements;
+               if (elements >= maxelem && SET_WITH_FORCEADD(set))
                        forceadd = true;
        }
+       rcu_read_unlock_bh();
 
-       t = ipset_dereference_protected(h->table, set);
-       key = HKEY(value, h->initval, t->htable_bits);
-       n = __ipset_dereference_protected(hbucket(t, key), 1);
+       spin_lock_bh(&t->hregion[r].lock);
+       n = rcu_dereference_bh(hbucket(t, key));
        if (!n) {
-               if (forceadd || set->elements >= h->maxelem)
+               if (forceadd || elements >= maxelem)
                        goto set_full;
                old = NULL;
                n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize,
                            GFP_ATOMIC);
-               if (!n)
-                       return -ENOMEM;
+               if (!n) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
                n->size = AHASH_INIT_SIZE;
-               set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+               t->hregion[r].ext_size +=
+                       ext_size(AHASH_INIT_SIZE, set->dsize);
                goto copy_elem;
        }
        for (i = 0; i < n->pos; i++) {
@@ -737,38 +916,37 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                }
                data = ahash_data(n, i, set->dsize);
                if (mtype_data_equal(data, d, &multi)) {
-                       if (flag_exist ||
-                           (SET_WITH_TIMEOUT(set) &&
-                            ip_set_timeout_expired(ext_timeout(data, set)))) {
+                       if (flag_exist || SET_ELEM_EXPIRED(set, data)) {
                                /* Just the extensions could be overwritten */
                                j = i;
                                goto overwrite_extensions;
                        }
-                       return -IPSET_ERR_EXIST;
+                       ret = -IPSET_ERR_EXIST;
+                       goto unlock;
                }
                /* Reuse first timed out entry */
-               if (SET_WITH_TIMEOUT(set) &&
-                   ip_set_timeout_expired(ext_timeout(data, set)) &&
-                   j == -1) {
+               if (SET_ELEM_EXPIRED(set, data) && j == -1) {
                        j = i;
                        reuse = true;
                }
        }
        if (reuse || forceadd) {
+               if (j == -1)
+                       j = 0;
                data = ahash_data(n, j, set->dsize);
                if (!deleted) {
 #ifdef IP_SET_HASH_WITH_NETS
                        for (i = 0; i < IPSET_NET_COUNT; i++)
-                               mtype_del_cidr(h,
+                               mtype_del_cidr(set, h,
                                        NCIDR_PUT(DCIDR_GET(data->cidr, i)),
                                        i);
 #endif
                        ip_set_ext_destroy(set, data);
-                       set->elements--;
+                       t->hregion[r].elements--;
                }
                goto copy_data;
        }
-       if (set->elements >= h->maxelem)
+       if (elements >= maxelem)
                goto set_full;
        /* Create a new slot */
        if (n->pos >= n->size) {
@@ -776,28 +954,32 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                if (n->size >= AHASH_MAX(h)) {
                        /* Trigger rehashing */
                        mtype_data_next(&h->next, d);
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto resize;
                }
                old = n;
                n = kzalloc(sizeof(*n) +
                            (old->size + AHASH_INIT_SIZE) * set->dsize,
                            GFP_ATOMIC);
-               if (!n)
-                       return -ENOMEM;
+               if (!n) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
                memcpy(n, old, sizeof(struct hbucket) +
                       old->size * set->dsize);
                n->size = old->size + AHASH_INIT_SIZE;
-               set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+               t->hregion[r].ext_size +=
+                       ext_size(AHASH_INIT_SIZE, set->dsize);
        }
 
 copy_elem:
        j = n->pos++;
        data = ahash_data(n, j, set->dsize);
 copy_data:
-       set->elements++;
+       t->hregion[r].elements++;
 #ifdef IP_SET_HASH_WITH_NETS
        for (i = 0; i < IPSET_NET_COUNT; i++)
-               mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
+               mtype_add_cidr(set, h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
 #endif
        memcpy(data, d, sizeof(struct mtype_elem));
 overwrite_extensions:
@@ -820,13 +1002,41 @@ overwrite_extensions:
                if (old)
                        kfree_rcu(old, rcu);
        }
+       ret = 0;
+resize:
+       spin_unlock_bh(&t->hregion[r].lock);
+       if (atomic_read(&t->ref) && ext->target) {
+               /* Resize is in process and kernel side add, save values */
+               struct mtype_resize_ad *x;
+
+               x = kzalloc(sizeof(struct mtype_resize_ad), GFP_ATOMIC);
+               if (!x)
+                       /* Don't bother */
+                       goto out;
+               x->ad = IPSET_ADD;
+               memcpy(&x->d, value, sizeof(struct mtype_elem));
+               memcpy(&x->ext, ext, sizeof(struct ip_set_ext));
+               memcpy(&x->mext, mext, sizeof(struct ip_set_ext));
+               x->flags = flags;
+               spin_lock_bh(&set->lock);
+               list_add_tail(&x->list, &h->ad);
+               spin_unlock_bh(&set->lock);
+       }
+       goto out;
 
-       return 0;
 set_full:
        if (net_ratelimit())
                pr_warn("Set %s is full, maxelem %u reached\n",
-                       set->name, h->maxelem);
-       return -IPSET_ERR_HASH_FULL;
+                       set->name, maxelem);
+       ret = -IPSET_ERR_HASH_FULL;
+unlock:
+       spin_unlock_bh(&t->hregion[r].lock);
+out:
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by add: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
+       return ret;
 }
 
 /* Delete an element from the hash and free up space if possible.
@@ -840,13 +1050,23 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        const struct mtype_elem *d = value;
        struct mtype_elem *data;
        struct hbucket *n;
-       int i, j, k, ret = -IPSET_ERR_EXIST;
+       struct mtype_resize_ad *x = NULL;
+       int i, j, k, r, ret = -IPSET_ERR_EXIST;
        u32 key, multi = 0;
        size_t dsize = set->dsize;
 
-       t = ipset_dereference_protected(h->table, set);
+       /* Userspace add and resize is excluded by the mutex.
+        * Kernespace add does not trigger resize.
+        */
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
        key = HKEY(value, h->initval, t->htable_bits);
-       n = __ipset_dereference_protected(hbucket(t, key), 1);
+       r = ahash_region(key, t->htable_bits);
+       atomic_inc(&t->uref);
+       rcu_read_unlock_bh();
+
+       spin_lock_bh(&t->hregion[r].lock);
+       n = rcu_dereference_bh(hbucket(t, key));
        if (!n)
                goto out;
        for (i = 0, k = 0; i < n->pos; i++) {
@@ -857,8 +1077,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                data = ahash_data(n, i, dsize);
                if (!mtype_data_equal(data, d, &multi))
                        continue;
-               if (SET_WITH_TIMEOUT(set) &&
-                   ip_set_timeout_expired(ext_timeout(data, set)))
+               if (SET_ELEM_EXPIRED(set, data))
                        goto out;
 
                ret = 0;
@@ -866,20 +1085,33 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                smp_mb__after_atomic();
                if (i + 1 == n->pos)
                        n->pos--;
-               set->elements--;
+               t->hregion[r].elements--;
 #ifdef IP_SET_HASH_WITH_NETS
                for (j = 0; j < IPSET_NET_COUNT; j++)
-                       mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)),
-                                      j);
+                       mtype_del_cidr(set, h,
+                                      NCIDR_PUT(DCIDR_GET(d->cidr, j)), j);
 #endif
                ip_set_ext_destroy(set, data);
 
+               if (atomic_read(&t->ref) && ext->target) {
+                       /* Resize is in process and kernel side del,
+                        * save values
+                        */
+                       x = kzalloc(sizeof(struct mtype_resize_ad),
+                                   GFP_ATOMIC);
+                       if (x) {
+                               x->ad = IPSET_DEL;
+                               memcpy(&x->d, value,
+                                      sizeof(struct mtype_elem));
+                               x->flags = flags;
+                       }
+               }
                for (; i < n->pos; i++) {
                        if (!test_bit(i, n->used))
                                k++;
                }
                if (n->pos == 0 && k == 0) {
-                       set->ext_size -= ext_size(n->size, dsize);
+                       t->hregion[r].ext_size -= ext_size(n->size, dsize);
                        rcu_assign_pointer(hbucket(t, key), NULL);
                        kfree_rcu(n, rcu);
                } else if (k >= AHASH_INIT_SIZE) {
@@ -898,7 +1130,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                                k++;
                        }
                        tmp->pos = k;
-                       set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+                       t->hregion[r].ext_size -=
+                               ext_size(AHASH_INIT_SIZE, dsize);
                        rcu_assign_pointer(hbucket(t, key), tmp);
                        kfree_rcu(n, rcu);
                }
@@ -906,6 +1139,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        }
 
 out:
+       spin_unlock_bh(&t->hregion[r].lock);
+       if (x) {
+               spin_lock_bh(&set->lock);
+               list_add(&x->list, &h->ad);
+               spin_unlock_bh(&set->lock);
+       }
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by del: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
        return ret;
 }
 
@@ -991,6 +1234,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        int i, ret = 0;
        u32 key, multi = 0;
 
+       rcu_read_lock_bh();
        t = rcu_dereference_bh(h->table);
 #ifdef IP_SET_HASH_WITH_NETS
        /* If we test an IP address and not a network address,
@@ -1022,6 +1266,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                        goto out;
        }
 out:
+       rcu_read_unlock_bh();
        return ret;
 }
 
@@ -1033,23 +1278,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
        const struct htable *t;
        struct nlattr *nested;
        size_t memsize;
+       u32 elements = 0;
+       size_t ext_size = 0;
        u8 htable_bits;
 
-       /* If any members have expired, set->elements will be wrong
-        * mytype_expire function will update it with the right count.
-        * we do not hold set->lock here, so grab it first.
-        * set->elements can still be incorrect in the case of a huge set,
-        * because elements might time out during the listing.
-        */
-       if (SET_WITH_TIMEOUT(set)) {
-               spin_lock_bh(&set->lock);
-               mtype_expire(set, h);
-               spin_unlock_bh(&set->lock);
-       }
-
        rcu_read_lock_bh();
-       t = rcu_dereference_bh_nfnl(h->table);
-       memsize = mtype_ahash_memsize(h, t) + set->ext_size;
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+       memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
        htable_bits = t->htable_bits;
        rcu_read_unlock_bh();
 
@@ -1071,7 +1307,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
 #endif
        if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
            nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
-           nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
+           nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements)))
                goto nla_put_failure;
        if (unlikely(ip_set_put_flags(skb, set)))
                goto nla_put_failure;
@@ -1091,15 +1327,15 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start)
 
        if (start) {
                rcu_read_lock_bh();
-               t = rcu_dereference_bh_nfnl(h->table);
+               t = ipset_dereference_bh_nfnl(h->table);
                atomic_inc(&t->uref);
                cb->args[IPSET_CB_PRIVATE] = (unsigned long)t;
                rcu_read_unlock_bh();
        } else if (cb->args[IPSET_CB_PRIVATE]) {
                t = (struct htable *)cb->args[IPSET_CB_PRIVATE];
                if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
-                       /* Resizing didn't destroy the hash table */
-                       pr_debug("Table destroy by dump: %p\n", t);
+                       pr_debug("Table destroy after resize "
+                                " by dump: %p\n", t);
                        mtype_ahash_destroy(set, t, false);
                }
                cb->args[IPSET_CB_PRIVATE] = 0;
@@ -1141,8 +1377,7 @@ mtype_list(const struct ip_set *set,
                        if (!test_bit(i, n->used))
                                continue;
                        e = ahash_data(n, i, set->dsize);
-                       if (SET_WITH_TIMEOUT(set) &&
-                           ip_set_timeout_expired(ext_timeout(e, set)))
+                       if (SET_ELEM_EXPIRED(set, e))
                                continue;
                        pr_debug("list hash %lu hbucket %p i %u, data %p\n",
                                 cb->args[IPSET_CB_ARG0], n, i, e);
@@ -1208,6 +1443,7 @@ static const struct ip_set_type_variant mtype_variant = {
        .uref   = mtype_uref,
        .resize = mtype_resize,
        .same_set = mtype_same_set,
+       .region_lock = true,
 };
 
 #ifdef IP_SET_EMIT_CREATE
@@ -1226,6 +1462,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
        size_t hsize;
        struct htype *h;
        struct htable *t;
+       u32 i;
 
        pr_debug("Create set %s with family %s\n",
                 set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
@@ -1294,6 +1531,15 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
                kfree(h);
                return -ENOMEM;
        }
+       t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits));
+       if (!t->hregion) {
+               kfree(t);
+               kfree(h);
+               return -ENOMEM;
+       }
+       h->gc.set = set;
+       for (i = 0; i < ahash_numof_locks(hbits); i++)
+               spin_lock_init(&t->hregion[i].lock);
        h->maxelem = maxelem;
 #ifdef IP_SET_HASH_WITH_NETMASK
        h->netmask = netmask;
@@ -1304,9 +1550,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
        get_random_bytes(&h->initval, sizeof(h->initval));
 
        t->htable_bits = hbits;
+       t->maxelem = h->maxelem / ahash_numof_locks(hbits);
        RCU_INIT_POINTER(h->table, t);
 
-       h->set = set;
+       INIT_LIST_HEAD(&h->ad);
        set->data = h;
 #ifndef IP_SET_PROTO_UNDEF
        if (set->family == NFPROTO_IPV4) {
@@ -1329,12 +1576,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
 #ifndef IP_SET_PROTO_UNDEF
                if (set->family == NFPROTO_IPV4)
 #endif
-                       IPSET_TOKEN(HTYPE, 4_gc_init)(set,
-                               IPSET_TOKEN(HTYPE, 4_gc));
+                       IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc);
 #ifndef IP_SET_PROTO_UNDEF
                else
-                       IPSET_TOKEN(HTYPE, 6_gc_init)(set,
-                               IPSET_TOKEN(HTYPE, 6_gc));
+                       IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc);
 #endif
        }
        pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
index d1305423640f3abfcaf7e3295022c765d31d82e5..1927fc296f9514bcd5866d340c6f659bea0fdb3e 100644 (file)
@@ -894,32 +894,175 @@ static void nf_ct_acct_merge(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        }
 }
 
-/* Resolve race on insertion if this protocol allows this. */
+static void __nf_conntrack_insert_prepare(struct nf_conn *ct)
+{
+       struct nf_conn_tstamp *tstamp;
+
+       atomic_inc(&ct->ct_general.use);
+       ct->status |= IPS_CONFIRMED;
+
+       /* set conntrack timestamp, if enabled. */
+       tstamp = nf_conn_tstamp_find(ct);
+       if (tstamp)
+               tstamp->start = ktime_get_real_ns();
+}
+
+static int __nf_ct_resolve_clash(struct sk_buff *skb,
+                                struct nf_conntrack_tuple_hash *h)
+{
+       /* This is the conntrack entry already in hashes that won race. */
+       struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *loser_ct;
+
+       loser_ct = nf_ct_get(skb, &ctinfo);
+
+       if (nf_ct_is_dying(ct))
+               return NF_DROP;
+
+       if (!atomic_inc_not_zero(&ct->ct_general.use))
+               return NF_DROP;
+
+       if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
+           nf_ct_match(ct, loser_ct)) {
+               struct net *net = nf_ct_net(ct);
+
+               nf_ct_acct_merge(ct, ctinfo, loser_ct);
+               nf_ct_add_to_dying_list(loser_ct);
+               nf_conntrack_put(&loser_ct->ct_general);
+               nf_ct_set(skb, ct, ctinfo);
+
+               NF_CT_STAT_INC(net, insert_failed);
+               return NF_ACCEPT;
+       }
+
+       nf_ct_put(ct);
+       return NF_DROP;
+}
+
+/**
+ * nf_ct_resolve_clash_harder - attempt to insert clashing conntrack entry
+ *
+ * @skb: skb that causes the collision
+ * @repl_idx: hash slot for reply direction
+ *
+ * Called when origin or reply direction had a clash.
+ * The skb can be handled without packet drop provided the reply direction
+ * is unique or there the existing entry has the identical tuple in both
+ * directions.
+ *
+ * Caller must hold conntrack table locks to prevent concurrent updates.
+ *
+ * Returns NF_DROP if the clash could not be handled.
+ */
+static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx)
+{
+       struct nf_conn *loser_ct = (struct nf_conn *)skb_nfct(skb);
+       const struct nf_conntrack_zone *zone;
+       struct nf_conntrack_tuple_hash *h;
+       struct hlist_nulls_node *n;
+       struct net *net;
+
+       zone = nf_ct_zone(loser_ct);
+       net = nf_ct_net(loser_ct);
+
+       /* Reply direction must never result in a clash, unless both origin
+        * and reply tuples are identical.
+        */
+       hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[repl_idx], hnnode) {
+               if (nf_ct_key_equal(h,
+                                   &loser_ct->tuplehash[IP_CT_DIR_REPLY].tuple,
+                                   zone, net))
+                       return __nf_ct_resolve_clash(skb, h);
+       }
+
+       /* We want the clashing entry to go away real soon: 1 second timeout. */
+       loser_ct->timeout = nfct_time_stamp + HZ;
+
+       /* IPS_NAT_CLASH removes the entry automatically on the first
+        * reply.  Also prevents UDP tracker from moving the entry to
+        * ASSURED state, i.e. the entry can always be evicted under
+        * pressure.
+        */
+       loser_ct->status |= IPS_FIXED_TIMEOUT | IPS_NAT_CLASH;
+
+       __nf_conntrack_insert_prepare(loser_ct);
+
+       /* fake add for ORIGINAL dir: we want lookups to only find the entry
+        * already in the table.  This also hides the clashing entry from
+        * ctnetlink iteration, i.e. conntrack -L won't show them.
+        */
+       hlist_nulls_add_fake(&loser_ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
+
+       hlist_nulls_add_head_rcu(&loser_ct->tuplehash[IP_CT_DIR_REPLY].hnnode,
+                                &nf_conntrack_hash[repl_idx]);
+       return NF_ACCEPT;
+}
+
+/**
+ * nf_ct_resolve_clash - attempt to handle clash without packet drop
+ *
+ * @skb: skb that causes the clash
+ * @h: tuplehash of the clashing entry already in table
+ * @hash_reply: hash slot for reply direction
+ *
+ * A conntrack entry can be inserted to the connection tracking table
+ * if there is no existing entry with an identical tuple.
+ *
+ * If there is one, @skb (and the assocated, unconfirmed conntrack) has
+ * to be dropped.  In case @skb is retransmitted, next conntrack lookup
+ * will find the already-existing entry.
+ *
+ * The major problem with such packet drop is the extra delay added by
+ * the packet loss -- it will take some time for a retransmit to occur
+ * (or the sender to time out when waiting for a reply).
+ *
+ * This function attempts to handle the situation without packet drop.
+ *
+ * If @skb has no NAT transformation or if the colliding entries are
+ * exactly the same, only the to-be-confirmed conntrack entry is discarded
+ * and @skb is associated with the conntrack entry already in the table.
+ *
+ * Failing that, the new, unconfirmed conntrack is still added to the table
+ * provided that the collision only occurs in the ORIGINAL direction.
+ * The new entry will be added after the existing one in the hash list,
+ * so packets in the ORIGINAL direction will continue to match the existing
+ * entry.  The new entry will also have a fixed timeout so it expires --
+ * due to the collision, it will not see bidirectional traffic.
+ *
+ * Returns NF_DROP if the clash could not be resolved.
+ */
 static __cold noinline int
-nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
-                   enum ip_conntrack_info ctinfo,
-                   struct nf_conntrack_tuple_hash *h)
+nf_ct_resolve_clash(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h,
+                   u32 reply_hash)
 {
        /* This is the conntrack entry already in hashes that won race. */
        struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
        const struct nf_conntrack_l4proto *l4proto;
-       enum ip_conntrack_info oldinfo;
-       struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo);
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *loser_ct;
+       struct net *net;
+       int ret;
+
+       loser_ct = nf_ct_get(skb, &ctinfo);
+       net = nf_ct_net(loser_ct);
 
        l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
-       if (l4proto->allow_clash &&
-           !nf_ct_is_dying(ct) &&
-           atomic_inc_not_zero(&ct->ct_general.use)) {
-               if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
-                   nf_ct_match(ct, loser_ct)) {
-                       nf_ct_acct_merge(ct, ctinfo, loser_ct);
-                       nf_conntrack_put(&loser_ct->ct_general);
-                       nf_ct_set(skb, ct, oldinfo);
-                       return NF_ACCEPT;
-               }
-               nf_ct_put(ct);
-       }
+       if (!l4proto->allow_clash)
+               goto drop;
+
+       ret = __nf_ct_resolve_clash(skb, h);
+       if (ret == NF_ACCEPT)
+               return ret;
+
+       ret = nf_ct_resolve_clash_harder(skb, reply_hash);
+       if (ret == NF_ACCEPT)
+               return ret;
+
+drop:
+       nf_ct_add_to_dying_list(loser_ct);
        NF_CT_STAT_INC(net, drop);
+       NF_CT_STAT_INC(net, insert_failed);
        return NF_DROP;
 }
 
@@ -932,7 +1075,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
        struct nf_conntrack_tuple_hash *h;
        struct nf_conn *ct;
        struct nf_conn_help *help;
-       struct nf_conn_tstamp *tstamp;
        struct hlist_nulls_node *n;
        enum ip_conntrack_info ctinfo;
        struct net *net;
@@ -989,6 +1131,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 
        if (unlikely(nf_ct_is_dying(ct))) {
                nf_ct_add_to_dying_list(ct);
+               NF_CT_STAT_INC(net, insert_failed);
                goto dying;
        }
 
@@ -1009,13 +1152,8 @@ __nf_conntrack_confirm(struct sk_buff *skb)
           setting time, otherwise we'd get timer wrap in
           weird delay cases. */
        ct->timeout += nfct_time_stamp;
-       atomic_inc(&ct->ct_general.use);
-       ct->status |= IPS_CONFIRMED;
 
-       /* set conntrack timestamp, if enabled. */
-       tstamp = nf_conn_tstamp_find(ct);
-       if (tstamp)
-               tstamp->start = ktime_get_real_ns();
+       __nf_conntrack_insert_prepare(ct);
 
        /* Since the lookup is lockless, hash insertion must be done after
         * starting the timer and setting the CONFIRMED bit. The RCU barriers
@@ -1035,11 +1173,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)
        return NF_ACCEPT;
 
 out:
-       nf_ct_add_to_dying_list(ct);
-       ret = nf_ct_resolve_clash(net, skb, ctinfo, h);
+       ret = nf_ct_resolve_clash(skb, h, reply_hash);
 dying:
        nf_conntrack_double_unlock(hash, reply_hash);
-       NF_CT_STAT_INC(net, insert_failed);
        local_bh_enable();
        return ret;
 }
index 7365b43f8f980edb267835006c8d7388ab450336..760ca242281655590ddf0a20ec25c8b73930e06f 100644 (file)
@@ -81,6 +81,18 @@ static bool udp_error(struct sk_buff *skb,
        return false;
 }
 
+static void nf_conntrack_udp_refresh_unreplied(struct nf_conn *ct,
+                                              struct sk_buff *skb,
+                                              enum ip_conntrack_info ctinfo,
+                                              u32 extra_jiffies)
+{
+       if (unlikely(ctinfo == IP_CT_ESTABLISHED_REPLY &&
+                    ct->status & IPS_NAT_CLASH))
+               nf_ct_kill(ct);
+       else
+               nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies);
+}
+
 /* Returns verdict for packet, and may modify conntracktype */
 int nf_conntrack_udp_packet(struct nf_conn *ct,
                            struct sk_buff *skb,
@@ -116,8 +128,8 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
        } else {
-               nf_ct_refresh_acct(ct, ctinfo, skb,
-                                  timeouts[UDP_CT_UNREPLIED]);
+               nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
+                                                  timeouts[UDP_CT_UNREPLIED]);
        }
        return NF_ACCEPT;
 }
@@ -198,8 +210,8 @@ int nf_conntrack_udplite_packet(struct nf_conn *ct,
                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
        } else {
-               nf_ct_refresh_acct(ct, ctinfo, skb,
-                                  timeouts[UDP_CT_UNREPLIED]);
+               nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
+                                                  timeouts[UDP_CT_UNREPLIED]);
        }
        return NF_ACCEPT;
 }
index 83e1db37c3b041f7872624d05dddd78a8b980404..06f00cdc389100fb197abba44e7fd208d4da23b8 100644 (file)
@@ -847,9 +847,6 @@ static int nf_flow_table_offload_cmd(struct flow_block_offload *bo,
 {
        int err;
 
-       if (!nf_flowtable_hw_offload(flowtable))
-               return 0;
-
        if (!dev->netdev_ops->ndo_setup_tc)
                return -EOPNOTSUPP;
 
@@ -876,6 +873,9 @@ int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
        struct flow_block_offload bo;
        int err;
 
+       if (!nf_flowtable_hw_offload(flowtable))
+               return 0;
+
        err = nf_flow_table_offload_cmd(&bo, flowtable, dev, cmd, &extack);
        if (err < 0)
                return err;
index f0cb1e13af5081216d799057ed5da4a314e0c4c7..4fc0c924ed5da0cc7adb99d4ba1c0ec8df636f1c 100644 (file)
  * ::
  *
  *       rule indices in last field:    0    1
- *       map to elements:             0x42  0x66
+ *       map to elements:             0x66  0x42
  *
  *
  * Matching
  * ::
  *
  *       rule indices in last field:    0    1
- *       map to elements:             0x42  0x66
+ *       map to elements:             0x66  0x42
  *
  *      the matching element is at 0x42.
  *
@@ -503,7 +503,7 @@ static int pipapo_refill(unsigned long *map, int len, int rules,
                                return -1;
                        }
 
-                       if (unlikely(match_only)) {
+                       if (match_only) {
                                bitmap_clear(map, i, 1);
                                return i;
                        }
@@ -1766,11 +1766,13 @@ static bool pipapo_match_field(struct nft_pipapo_field *f,
 static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                              const struct nft_set_elem *elem)
 {
-       const u8 *data = (const u8 *)elem->key.val.data;
        struct nft_pipapo *priv = nft_set_priv(set);
        struct nft_pipapo_match *m = priv->clone;
+       struct nft_pipapo_elem *e = elem->priv;
        int rules_f0, first_rule = 0;
-       struct nft_pipapo_elem *e;
+       const u8 *data;
+
+       data = (const u8 *)nft_set_ext_key(&e->ext);
 
        e = pipapo_get(net, set, data, 0);
        if (IS_ERR(e))
index bccd47cd7190810af06dea672842be7f58f72a4e..8c835ad637290efc7505bcfd64507c731a94e364 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/mutex.h>
 #include <linux/kernel.h>
+#include <linux/refcount.h>
 #include <uapi/linux/netfilter/xt_hashlimit.h>
 
 #define XT_HASHLIMIT_ALL (XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT | \
@@ -114,7 +115,7 @@ struct dsthash_ent {
 
 struct xt_hashlimit_htable {
        struct hlist_node node;         /* global list of all htables */
-       int use;
+       refcount_t use;
        u_int8_t family;
        bool rnd_initialized;
 
@@ -315,7 +316,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
        for (i = 0; i < hinfo->cfg.size; i++)
                INIT_HLIST_HEAD(&hinfo->hash[i]);
 
-       hinfo->use = 1;
+       refcount_set(&hinfo->use, 1);
        hinfo->count = 0;
        hinfo->family = family;
        hinfo->rnd_initialized = false;
@@ -401,15 +402,6 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo)
                remove_proc_entry(hinfo->name, parent);
 }
 
-static void htable_destroy(struct xt_hashlimit_htable *hinfo)
-{
-       cancel_delayed_work_sync(&hinfo->gc_work);
-       htable_remove_proc_entry(hinfo);
-       htable_selective_cleanup(hinfo, true);
-       kfree(hinfo->name);
-       vfree(hinfo);
-}
-
 static struct xt_hashlimit_htable *htable_find_get(struct net *net,
                                                   const char *name,
                                                   u_int8_t family)
@@ -420,7 +412,7 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) {
                if (!strcmp(name, hinfo->name) &&
                    hinfo->family == family) {
-                       hinfo->use++;
+                       refcount_inc(&hinfo->use);
                        return hinfo;
                }
        }
@@ -429,12 +421,16 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
 
 static void htable_put(struct xt_hashlimit_htable *hinfo)
 {
-       mutex_lock(&hashlimit_mutex);
-       if (--hinfo->use == 0) {
+       if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) {
                hlist_del(&hinfo->node);
-               htable_destroy(hinfo);
+               htable_remove_proc_entry(hinfo);
+               mutex_unlock(&hashlimit_mutex);
+
+               cancel_delayed_work_sync(&hinfo->gc_work);
+               htable_selective_cleanup(hinfo, true);
+               kfree(hinfo->name);
+               vfree(hinfo);
        }
-       mutex_unlock(&hashlimit_mutex);
 }
 
 /* The algorithm used is the Simple Token Bucket Filter (TBF)
@@ -837,6 +833,8 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
        return hashlimit_mt_common(skb, par, hinfo, &info->cfg, 3);
 }
 
+#define HASHLIMIT_MAX_SIZE 1048576
+
 static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
                                     struct xt_hashlimit_htable **hinfo,
                                     struct hashlimit_cfg3 *cfg,
@@ -847,6 +845,14 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
 
        if (cfg->gc_interval == 0 || cfg->expire == 0)
                return -EINVAL;
+       if (cfg->size > HASHLIMIT_MAX_SIZE) {
+               cfg->size = HASHLIMIT_MAX_SIZE;
+               pr_info_ratelimited("size too large, truncated to %u\n", cfg->size);
+       }
+       if (cfg->max > HASHLIMIT_MAX_SIZE) {
+               cfg->max = HASHLIMIT_MAX_SIZE;
+               pr_info_ratelimited("max too large, truncated to %u\n", cfg->max);
+       }
        if (par->family == NFPROTO_IPV4) {
                if (cfg->srcmask > 32 || cfg->dstmask > 32)
                        return -EINVAL;
index f5d34da0646eda1647a39300252ff1249c8b01eb..a1f2320ecc16d1450525123fe6f217ddb8203b76 100644 (file)
@@ -143,7 +143,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain,
        if (domain != NULL) {
                bkt = netlbl_domhsh_hash(domain);
                bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];
-               list_for_each_entry_rcu(iter, bkt_list, list)
+               list_for_each_entry_rcu(iter, bkt_list, list,
+                                       lockdep_is_held(&netlbl_domhsh_lock))
                        if (iter->valid &&
                            netlbl_family_match(iter->family, family) &&
                            strcmp(iter->domain, domain) == 0)
index d2e4ab8d1cb1008da0a9577667d1206d4c0bb309..77bb1bb22c3bfced3a6302d4241f5a0cdbd5d069 100644 (file)
@@ -207,7 +207,8 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
 
        bkt = netlbl_unlhsh_hash(ifindex);
        bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
-       list_for_each_entry_rcu(iter, bkt_list, list)
+       list_for_each_entry_rcu(iter, bkt_list, list,
+                               lockdep_is_held(&netlbl_unlhsh_lock))
                if (iter->valid && iter->ifindex == ifindex)
                        return iter;
 
index 4e31721e729360c8bf555186ab6d4aa67cb00280..edf3e285e242877d78b044bac89b4a41804b56cb 100644 (file)
@@ -1014,7 +1014,8 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
        if (nlk->netlink_bind && groups) {
                int group;
 
-               for (group = 0; group < nlk->ngroups; group++) {
+               /* nl_groups is a u32, so cap the maximum groups we can bind */
+               for (group = 0; group < BITS_PER_TYPE(u32); group++) {
                        if (!test_bit(group, &groups))
                                continue;
                        err = nlk->netlink_bind(net, group + 1);
@@ -1033,7 +1034,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        netlink_insert(sk, nladdr->nl_pid) :
                        netlink_autobind(sock);
                if (err) {
-                       netlink_undo_bind(nlk->ngroups, groups, sk);
+                       netlink_undo_bind(BITS_PER_TYPE(u32), groups, sk);
                        goto unlock;
                }
        }
index 0522b2b1fd958ce17de51163df8505d2b754d988..9f357aa22b9452d17f5c391a159d263c4f3df552 100644 (file)
@@ -497,8 +497,9 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
 
        err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
                            family->policy, validate, extack);
-       if (err && parallel) {
-               kfree(attrbuf);
+       if (err) {
+               if (parallel)
+                       kfree(attrbuf);
                return ERR_PTR(err);
        }
        return attrbuf;
index 659c2a790fe7cf919d3b5b6af3bd41ffde1211c7..c047afd121160f4fd66d4fcd135eb15dd2dbc6e7 100644 (file)
@@ -179,7 +179,8 @@ struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
        struct hlist_head *head;
 
        head = vport_hash_bucket(dp, port_no);
-       hlist_for_each_entry_rcu(vport, head, dp_hash_node) {
+       hlist_for_each_entry_rcu(vport, head, dp_hash_node,
+                               lockdep_ovsl_is_held()) {
                if (vport->port_no == port_no)
                        return vport;
        }
@@ -2042,7 +2043,8 @@ static unsigned int ovs_get_max_headroom(struct datapath *dp)
        int i;
 
        for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
-               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
+               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node,
+                                       lockdep_ovsl_is_held()) {
                        dev = vport->dev;
                        dev_headroom = netdev_get_fwd_headroom(dev);
                        if (dev_headroom > max_headroom)
@@ -2061,7 +2063,8 @@ static void ovs_update_headroom(struct datapath *dp, unsigned int new_headroom)
 
        dp->max_headroom = new_headroom;
        for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
-               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node)
+               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node,
+                                       lockdep_ovsl_is_held())
                        netdev_set_rx_headroom(vport->dev, new_headroom);
 }
 
index 7da4230627f51489707fc199c4333702c344282e..288122eec7c838abcadcd0c106a719675c84471e 100644 (file)
@@ -2708,10 +2708,6 @@ static int validate_set(const struct nlattr *a,
                return -EINVAL;
 
        switch (key_type) {
-       const struct ovs_key_ipv4 *ipv4_key;
-       const struct ovs_key_ipv6 *ipv6_key;
-       int err;
-
        case OVS_KEY_ATTR_PRIORITY:
        case OVS_KEY_ATTR_SKB_MARK:
        case OVS_KEY_ATTR_CT_MARK:
@@ -2723,7 +2719,9 @@ static int validate_set(const struct nlattr *a,
                        return -EINVAL;
                break;
 
-       case OVS_KEY_ATTR_TUNNEL:
+       case OVS_KEY_ATTR_TUNNEL: {
+               int err;
+
                if (masked)
                        return -EINVAL; /* Masked tunnel set not supported. */
 
@@ -2732,8 +2730,10 @@ static int validate_set(const struct nlattr *a,
                if (err)
                        return err;
                break;
+       }
+       case OVS_KEY_ATTR_IPV4: {
+               const struct ovs_key_ipv4 *ipv4_key;
 
-       case OVS_KEY_ATTR_IPV4:
                if (eth_type != htons(ETH_P_IP))
                        return -EINVAL;
 
@@ -2753,8 +2753,10 @@ static int validate_set(const struct nlattr *a,
                                return -EINVAL;
                }
                break;
+       }
+       case OVS_KEY_ATTR_IPV6: {
+               const struct ovs_key_ipv6 *ipv6_key;
 
-       case OVS_KEY_ATTR_IPV6:
                if (eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
 
@@ -2781,7 +2783,7 @@ static int validate_set(const struct nlattr *a,
                        return -EINVAL;
 
                break;
-
+       }
        case OVS_KEY_ATTR_TCP:
                if ((eth_type != htons(ETH_P_IP) &&
                     eth_type != htons(ETH_P_IPV6)) ||
index 5904e93e57656d80632b00e288292706e8597ef9..fd8a01ca7a2d53d72766d5234e1f133caf4be68e 100644 (file)
@@ -585,7 +585,8 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
        head = find_bucket(ti, hash);
        (*n_mask_hit)++;
 
-       hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) {
+       hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver],
+                               lockdep_ovsl_is_held()) {
                if (flow->mask == mask && flow->flow_table.hash == hash &&
                    flow_cmp_masked_key(flow, &masked_key, &mask->range))
                        return flow;
@@ -769,7 +770,8 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
 
        hash = ufid_hash(ufid);
        head = find_bucket(ti, hash);
-       hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver]) {
+       hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver],
+                               lockdep_ovsl_is_held()) {
                if (flow->ufid_table.hash == hash &&
                    ovs_flow_cmp_ufid(flow, ufid))
                        return flow;
index 3323b79ff548dfbf7842b3ac3b825b7d0f7dcfde..5010d1ddd4bdb1f8b5fd34dbc97c7b3803552563 100644 (file)
@@ -61,7 +61,8 @@ static struct dp_meter *lookup_meter(const struct datapath *dp,
        struct hlist_head *head;
 
        head = meter_hash_bucket(dp, meter_id);
-       hlist_for_each_entry_rcu(meter, head, dp_hash_node) {
+       hlist_for_each_entry_rcu(meter, head, dp_hash_node,
+                               lockdep_ovsl_is_held()) {
                if (meter->id == meter_id)
                        return meter;
        }
index 5da9392b03d624c2ae56b67366d3922e0000b079..47febb4504f098d2be91a1072fdd1daac71a9462 100644 (file)
@@ -96,7 +96,8 @@ struct vport *ovs_vport_locate(const struct net *net, const char *name)
        struct hlist_head *bucket = hash_bucket(net, name);
        struct vport *vport;
 
-       hlist_for_each_entry_rcu(vport, bucket, hash_node)
+       hlist_for_each_entry_rcu(vport, bucket, hash_node,
+                               lockdep_ovsl_is_held())
                if (!strcmp(name, ovs_vport_name(vport)) &&
                    net_eq(ovs_dp_get_net(vport->dp), net))
                        return vport;
index 3341eee87bf9b3c8bad89b88ca0e8fcd74186539..585e6b3b69ce4c32ec9404ee5ad88065b0979f75 100644 (file)
@@ -162,10 +162,9 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
        if (write)
                gup_flags |= FOLL_WRITE;
 
-       ret = get_user_pages_fast(user_addr, nr_pages, gup_flags, pages);
+       ret = pin_user_pages_fast(user_addr, nr_pages, gup_flags, pages);
        if (ret >= 0 && ret < nr_pages) {
-               while (ret--)
-                       put_page(pages[ret]);
+               unpin_user_pages(pages, ret);
                ret = -EFAULT;
        }
 
@@ -300,8 +299,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
                 * to release anything.
                 */
                if (!need_odp) {
-                       for (i = 0 ; i < nents; i++)
-                               put_page(sg_page(&sg[i]));
+                       unpin_user_pages(pages, nr_pages);
                        kfree(sg);
                }
                ret = PTR_ERR(trans_private);
@@ -325,7 +323,12 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
        if (cookie_ret)
                *cookie_ret = cookie;
 
-       if (args->cookie_addr && put_user(cookie, (u64 __user *)(unsigned long) args->cookie_addr)) {
+       if (args->cookie_addr &&
+           put_user(cookie, (u64 __user *)(unsigned long)args->cookie_addr)) {
+               if (!need_odp) {
+                       unpin_user_pages(pages, nr_pages);
+                       kfree(sg);
+               }
                ret = -EFAULT;
                goto out;
        }
@@ -496,9 +499,7 @@ void rds_rdma_free_op(struct rm_rdma_op *ro)
                         * is the case for a RDMA_READ which copies from remote
                         * to local memory
                         */
-                       if (!ro->op_write)
-                               set_page_dirty(page);
-                       put_page(page);
+                       unpin_user_pages_dirty_lock(&page, 1, !ro->op_write);
                }
        }
 
@@ -515,8 +516,7 @@ void rds_atomic_free_op(struct rm_atomic_op *ao)
        /* Mark page dirty if it was possibly modified, which
         * is the case for a RDMA_READ which copies from remote
         * to local memory */
-       set_page_dirty(page);
-       put_page(page);
+       unpin_user_pages_dirty_lock(&page, 1, true);
 
        kfree(ao->op_notifier);
        ao->op_notifier = NULL;
@@ -944,7 +944,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
        return ret;
 err:
        if (page)
-               put_page(page);
+               unpin_user_page(page);
        rm->atomic.op_active = 0;
        kfree(rm->atomic.op_notifier);
 
index 90a31b15585f61a5a3c406eb3e3985679164e044..8c466a712cda047001973652603c4f0e0c4e2b4d 100644 (file)
@@ -186,6 +186,7 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
                + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
                + cookie_len /* TCA_ACT_COOKIE */
                + nla_total_size(0) /* TCA_ACT_STATS nested */
+               + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */
                /* TCA_STATS_BASIC */
                + nla_total_size_64bit(sizeof(struct gnet_stats_basic))
                /* TCA_STATS_PKT64 */
index 7e54d2ab52547bde8dc4b5e6adee5693063c4061..d32d4233d33748c302600a229d207dcab3644266 100644 (file)
@@ -305,6 +305,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        struct cls_fl_filter *f;
 
        list_for_each_entry_rcu(mask, &head->masks, list) {
+               flow_dissector_init_keys(&skb_key.control, &skb_key.basic);
                fl_clear_masked_range(&skb_key, mask);
 
                skb_flow_dissect_meta(skb, &mask->dissector, &skb_key);
index 748e3b19ec1dc2c7d8ed1dbc83193b7f077c7eb2..6a16af4b1ef61810fed8a04169109f311b070575 100644 (file)
@@ -170,6 +170,16 @@ static inline bool sctp_chunk_length_valid(struct sctp_chunk *chunk,
        return true;
 }
 
+/* Check for format error in an ABORT chunk */
+static inline bool sctp_err_chunk_valid(struct sctp_chunk *chunk)
+{
+       struct sctp_errhdr *err;
+
+       sctp_walk_errors(err, chunk->chunk_hdr);
+
+       return (void *)err == (void *)chunk->chunk_end;
+}
+
 /**********************************************************
  * These are the state functions for handling chunk events.
  **********************************************************/
@@ -2255,6 +2265,9 @@ enum sctp_disposition sctp_sf_shutdown_pending_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
 }
 
@@ -2298,6 +2311,9 @@ enum sctp_disposition sctp_sf_shutdown_sent_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        /* Stop the T2-shutdown timer. */
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
@@ -2565,6 +2581,9 @@ enum sctp_disposition sctp_sf_do_9_1_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
 }
 
@@ -2582,16 +2601,8 @@ static enum sctp_disposition __sctp_sf_do_9_1_abort(
 
        /* See if we have an error cause code in the chunk.  */
        len = ntohs(chunk->chunk_hdr->length);
-       if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) {
-               struct sctp_errhdr *err;
-
-               sctp_walk_errors(err, chunk->chunk_hdr);
-               if ((void *)err != (void *)chunk->chunk_end)
-                       return sctp_sf_pdiscard(net, ep, asoc, type, arg,
-                                               commands);
-
+       if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
                error = ((struct sctp_errhdr *)chunk->skb->data)->cause;
-       }
 
        sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
        /* ASSOC_FAILED will DELETE_TCB. */
index 90988a511cd522e55ff04469a861bf05b99908ae..6fd44bdb0fc3ebb8d9b32e5aebbb494267d71b27 100644 (file)
@@ -512,15 +512,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
 static int smc_connect_abort(struct smc_sock *smc, int reason_code,
                             int local_contact)
 {
+       bool is_smcd = smc->conn.lgr->is_smcd;
+
        if (local_contact == SMC_FIRST_CONTACT)
-               smc_lgr_forget(smc->conn.lgr);
-       if (smc->conn.lgr->is_smcd)
+               smc_lgr_cleanup_early(&smc->conn);
+       else
+               smc_conn_free(&smc->conn);
+       if (is_smcd)
                /* there is only one lgr role for SMC-D; use server lock */
                mutex_unlock(&smc_server_lgr_pending);
        else
                mutex_unlock(&smc_client_lgr_pending);
 
-       smc_conn_free(&smc->conn);
        smc->connect_nonblock = 0;
        return reason_code;
 }
@@ -1091,7 +1094,6 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
        if (newsmcsk->sk_state == SMC_INIT)
                sock_put(&new_smc->sk); /* passive closing */
        newsmcsk->sk_state = SMC_CLOSED;
-       smc_conn_free(&new_smc->conn);
 
        smc_listen_out(new_smc);
 }
@@ -1102,12 +1104,13 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
 {
        /* RDMA setup failed, switch back to TCP */
        if (local_contact == SMC_FIRST_CONTACT)
-               smc_lgr_forget(new_smc->conn.lgr);
+               smc_lgr_cleanup_early(&new_smc->conn);
+       else
+               smc_conn_free(&new_smc->conn);
        if (reason_code < 0) { /* error, no fallback possible */
                smc_listen_out_err(new_smc);
                return;
        }
-       smc_conn_free(&new_smc->conn);
        smc_switch_to_fallback(new_smc);
        new_smc->fallback_rsn = reason_code;
        if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) {
@@ -1170,16 +1173,18 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
                            new_smc->conn.lgr->vlan_id,
                            new_smc->conn.lgr->smcd)) {
                if (ini->cln_first_contact == SMC_FIRST_CONTACT)
-                       smc_lgr_forget(new_smc->conn.lgr);
-               smc_conn_free(&new_smc->conn);
+                       smc_lgr_cleanup_early(&new_smc->conn);
+               else
+                       smc_conn_free(&new_smc->conn);
                return SMC_CLC_DECL_SMCDNOTALK;
        }
 
        /* Create send and receive buffers */
        if (smc_buf_create(new_smc, true)) {
                if (ini->cln_first_contact == SMC_FIRST_CONTACT)
-                       smc_lgr_forget(new_smc->conn.lgr);
-               smc_conn_free(&new_smc->conn);
+                       smc_lgr_cleanup_early(&new_smc->conn);
+               else
+                       smc_conn_free(&new_smc->conn);
                return SMC_CLC_DECL_MEM;
        }
 
index 2249de5379ee900301cc9fc34cf84b51085399f5..5b085efa3bce49e4cc10185c90d61ef1ece7c5c0 100644 (file)
@@ -162,6 +162,18 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
        conn->lgr = NULL;
 }
 
+void smc_lgr_cleanup_early(struct smc_connection *conn)
+{
+       struct smc_link_group *lgr = conn->lgr;
+
+       if (!lgr)
+               return;
+
+       smc_conn_free(conn);
+       smc_lgr_forget(lgr);
+       smc_lgr_schedule_free_work_fast(lgr);
+}
+
 /* Send delete link, either as client to request the initiation
  * of the DELETE LINK sequence from server; or as server to
  * initiate the delete processing. See smc_llc_rx_delete_link().
index c472e12951d1abbf52c8ab44f041b3042605b5e6..234ae25f0025f1ea641ce20868d0dd9e9bf8e814 100644 (file)
@@ -296,6 +296,7 @@ struct smc_clc_msg_accept_confirm;
 struct smc_clc_msg_local;
 
 void smc_lgr_forget(struct smc_link_group *lgr);
+void smc_lgr_cleanup_early(struct smc_connection *conn);
 void smc_lgr_terminate(struct smc_link_group *lgr, bool soft);
 void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
 void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
@@ -316,7 +317,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini);
 
 void smc_conn_free(struct smc_connection *conn);
 int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini);
-void smcd_conn_free(struct smc_connection *conn);
 void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr);
 int smc_core_init(void);
 void smc_core_exit(void);
index 548632621f4bc952b973c920af68f6477f0acc2b..d6ba186f67e2aa16d8f3822bea0950f0cb6612cc 100644 (file)
@@ -573,6 +573,8 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data)
        struct smc_ib_device *smcibdev;
 
        smcibdev = ib_get_client_data(ibdev, &smc_ib_client);
+       if (!smcibdev || smcibdev->ibdev != ibdev)
+               return;
        ib_set_client_data(ibdev, &smc_ib_client, NULL);
        spin_lock(&smc_ib_devices.lock);
        list_del_init(&smcibdev->list); /* remove from smc_ib_devices */
index 1ba5a92832bb0e065e0e9b8ac6f742b24d1d13c5..1c5574e2e05825140fd4b2ffc2ecd636147aba63 100644 (file)
@@ -593,7 +593,7 @@ struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
                                       u32 seq, u64 *p_record_sn)
 {
        u64 record_sn = context->hint_record_sn;
-       struct tls_record_info *info;
+       struct tls_record_info *info, *last;
 
        info = context->retransmit_hint;
        if (!info ||
@@ -605,6 +605,24 @@ struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
                                                struct tls_record_info, list);
                if (!info)
                        return NULL;
+               /* send the start_marker record if seq number is before the
+                * tls offload start marker sequence number. This record is
+                * required to handle TCP packets which are before TLS offload
+                * started.
+                *  And if it's not start marker, look if this seq number
+                * belongs to the list.
+                */
+               if (likely(!tls_record_is_start_marker(info))) {
+                       /* we have the first record, get the last record to see
+                        * if this seq number belongs to the list.
+                        */
+                       last = list_last_entry(&context->records_list,
+                                              struct tls_record_info, list);
+
+                       if (!between(seq, tls_record_start_seq(info),
+                                    last->end_seq))
+                               return NULL;
+               }
                record_sn = context->unacked_record_sn;
        }
 
index 62c12cb5763e6d0ec4ef7daefd6836b6588b7185..68debcb28fa4c46eb2b75b0ec262958299eda960 100644 (file)
@@ -682,6 +682,7 @@ static int unix_set_peek_off(struct sock *sk, int val)
        return 0;
 }
 
+#ifdef CONFIG_PROC_FS
 static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
 {
        struct sock *sk = sock->sk;
@@ -692,6 +693,9 @@ static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
                seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds));
        }
 }
+#else
+#define unix_show_fdinfo NULL
+#endif
 
 static const struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
index 9c5b2a91baad60945cd06881c57d1b0c56810a58..a5f28708e0e75402e595a38ee91c57e9637e0289 100644 (file)
@@ -451,6 +451,12 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
                if (vsk->transport == new_transport)
                        return 0;
 
+               /* transport->release() must be called with sock lock acquired.
+                * This path can only be taken during vsock_stream_connect(),
+                * where we have already held the sock lock.
+                * In the other cases, this function is called on a new socket
+                * which is not assigned to any transport.
+                */
                vsk->transport->release(vsk);
                vsock_deassign_transport(vsk);
        }
@@ -753,20 +759,18 @@ static void __vsock_release(struct sock *sk, int level)
                vsk = vsock_sk(sk);
                pending = NULL; /* Compiler warning. */
 
-               /* The release call is supposed to use lock_sock_nested()
-                * rather than lock_sock(), if a sock lock should be acquired.
-                */
-               if (vsk->transport)
-                       vsk->transport->release(vsk);
-               else if (sk->sk_type == SOCK_STREAM)
-                       vsock_remove_sock(vsk);
-
                /* When "level" is SINGLE_DEPTH_NESTING, use the nested
                 * version to avoid the warning "possible recursive locking
                 * detected". When "level" is 0, lock_sock_nested(sk, level)
                 * is the same as lock_sock(sk).
                 */
                lock_sock_nested(sk, level);
+
+               if (vsk->transport)
+                       vsk->transport->release(vsk);
+               else if (sk->sk_type == SOCK_STREAM)
+                       vsock_remove_sock(vsk);
+
                sock_orphan(sk);
                sk->sk_shutdown = SHUTDOWN_MASK;
 
index 3492c021925f4b2163ff5aff46d334ae64bbdc41..630b851f8150fd2e67eac5187d75a1771b82f068 100644 (file)
@@ -526,12 +526,9 @@ static bool hvs_close_lock_held(struct vsock_sock *vsk)
 
 static void hvs_release(struct vsock_sock *vsk)
 {
-       struct sock *sk = sk_vsock(vsk);
        bool remove_sock;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        remove_sock = hvs_close_lock_held(vsk);
-       release_sock(sk);
        if (remove_sock)
                vsock_remove_sock(vsk);
 }
index d9f0c9c5425a424c2c54e7794cd97764a9735ee1..f3c4bab2f737c97c08e38237b8108209f45eccad 100644 (file)
@@ -829,7 +829,6 @@ void virtio_transport_release(struct vsock_sock *vsk)
        struct sock *sk = &vsk->sk;
        bool remove_sock = true;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        if (sk->sk_type == SOCK_STREAM)
                remove_sock = virtio_transport_close(vsk);
 
@@ -837,7 +836,6 @@ void virtio_transport_release(struct vsock_sock *vsk)
                list_del(&pkt->list);
                virtio_transport_free_pkt(pkt);
        }
-       release_sock(sk);
 
        if (remove_sock)
                vsock_remove_sock(vsk);
index cedf17d4933f4ccdd8387dae144b75a8b43b9a53..5b19e9fac4aac68e9ce222610fa8a75f9b1a9c29 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/netlink.h>
 #include <linux/nospec.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <net/net_namespace.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
@@ -4800,8 +4801,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                err = nl80211_parse_he_obss_pd(
                                        info->attrs[NL80211_ATTR_HE_OBSS_PD],
                                        &params.he_obss_pd);
-               if (err)
-                       return err;
+               goto out;
        }
 
        nl80211_calculate_ap_params(&params);
@@ -4823,6 +4823,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        }
        wdev_unlock(wdev);
 
+out:
        kfree(params.acl);
 
        return err;
index fff9a74891fc433e5ac05970b23aa7f13adaad78..1a8218f1bbe075457441e39da8e14220e375701d 100644 (file)
@@ -2276,7 +2276,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
                        break;
        }
 
-       if (IS_ERR(reg_rule)) {
+       if (IS_ERR_OR_NULL(reg_rule)) {
                pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n",
                         chan->center_freq);
                if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
index df600487a68d513c3f7abcb1b584d2f4c229a7dd..356f90e4522b4cc39bf05ae4765d0517c43e5dc4 100644 (file)
@@ -217,6 +217,7 @@ static int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
 static void xsk_flush(struct xdp_sock *xs)
 {
        xskq_prod_submit(xs->rx);
+       __xskq_cons_release(xs->umem->fq);
        sock_def_readable(&xs->sk);
 }
 
@@ -304,6 +305,7 @@ void xsk_umem_consume_tx_done(struct xdp_umem *umem)
 
        rcu_read_lock();
        list_for_each_entry_rcu(xs, &umem->xsk_list, list) {
+               __xskq_cons_release(xs->tx);
                xs->sk.sk_write_space(&xs->sk);
        }
        rcu_read_unlock();
index bec2af11853addb48c658b7e046383ef8025169f..89a01ac4e07965cfafc342d205fbf21edc366c0b 100644 (file)
@@ -271,7 +271,8 @@ static inline void xskq_cons_release(struct xsk_queue *q)
 {
        /* To improve performance, only update local state here.
         * Reflect this to global state when we get new entries
-        * from the ring in xskq_cons_get_entries().
+        * from the ring in xskq_cons_get_entries() and whenever
+        * Rx or Tx processing are completed in the NAPI loop.
         */
        q->cached_cons++;
 }
index bae62549e3d2a3308b1683f375fd4d9004cbe6f2..752ff0a225a9d3d4caaf824ac7a2272743234451 100644 (file)
@@ -300,15 +300,15 @@ DT_BINDING_DIR := Documentation/devicetree/bindings
 DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml
 
 quiet_cmd_dtb_check =  CHECK   $@
-      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ ;
+      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
 
-define rule_dtc_dt_yaml
+define rule_dtc
        $(call cmd_and_fixdep,dtc,yaml)
        $(call cmd,dtb_check)
 endef
 
 $(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
-       $(call if_changed_rule,dtc_dt_yaml)
+       $(call if_changed_rule,dtc)
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
index 34085d146fa2cadb0a92353c0f6cc0d89303af29..6cbcd1a3e113c1f5866fc02ae4f8b40f16276be0 100755 (executable)
@@ -932,10 +932,6 @@ sub get_maintainers {
        }
     }
 
-    foreach my $fix (@fixes) {
-       vcs_add_commit_signers($fix, "blamed_fixes");
-    }
-
     foreach my $email (@email_to, @list_to) {
        $email->[0] = deduplicate_email($email->[0]);
     }
@@ -974,6 +970,10 @@ sub get_maintainers {
        }
     }
 
+    foreach my $fix (@fixes) {
+       vcs_add_commit_signers($fix, "blamed_fixes");
+    }
+
     my @to = ();
     if ($email || $email_list) {
        if ($email) {
@@ -1341,35 +1341,11 @@ sub add_categories {
                    }
                }
            } elsif ($ptype eq "M") {
-               my ($name, $address) = parse_email($pvalue);
-               if ($name eq "") {
-                   if ($i > 0) {
-                       my $tv = $typevalue[$i - 1];
-                       if ($tv =~ m/^([A-Z]):\s*(.*)/) {
-                           if ($1 eq "P") {
-                               $name = $2;
-                               $pvalue = format_email($name, $address, $email_usename);
-                           }
-                       }
-                   }
-               }
                if ($email_maintainer) {
                    my $role = get_maintainer_role($i);
                    push_email_addresses($pvalue, $role);
                }
            } elsif ($ptype eq "R") {
-               my ($name, $address) = parse_email($pvalue);
-               if ($name eq "") {
-                   if ($i > 0) {
-                       my $tv = $typevalue[$i - 1];
-                       if ($tv =~ m/^([A-Z]):\s*(.*)/) {
-                           if ($1 eq "P") {
-                               $name = $2;
-                               $pvalue = format_email($name, $address, $email_usename);
-                           }
-                       }
-                   }
-               }
                if ($email_reviewer) {
                    my $subsystem = get_subsystem_name($i);
                    push_email_addresses($pvalue, "reviewer:$subsystem");
index 711ff10fa36eca6ad201deca04abc41ff2858339..3f3ee4e2eb0d1c739ca57f93ad1dd7fe421157ff 100644 (file)
@@ -112,6 +112,10 @@ choice
        config IMA_DEFAULT_HASH_WP512
                bool "WP512"
                depends on CRYPTO_WP512=y && !IMA_TEMPLATE
+
+       config IMA_DEFAULT_HASH_SM3
+               bool "SM3"
+               depends on CRYPTO_SM3=y && !IMA_TEMPLATE
 endchoice
 
 config IMA_DEFAULT_HASH
@@ -121,6 +125,7 @@ config IMA_DEFAULT_HASH
        default "sha256" if IMA_DEFAULT_HASH_SHA256
        default "sha512" if IMA_DEFAULT_HASH_SHA512
        default "wp512" if IMA_DEFAULT_HASH_WP512
+       default "sm3" if IMA_DEFAULT_HASH_SM3
 
 config IMA_WRITE_POLICY
        bool "Enable multiple writes to the IMA policy"
index 111898aad56e48b99d93d55411adedbc82ad8670..f0c908241966ae3f387a55d4ddc813150135b91b 100644 (file)
@@ -35,16 +35,18 @@ static __init bool uefi_check_ignore_db(void)
  * Get a certificate list blob from the named EFI variable.
  */
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
-                                 unsigned long *size)
+                                 unsigned long *size, efi_status_t *status)
 {
-       efi_status_t status;
        unsigned long lsize = 4;
        unsigned long tmpdb[4];
        void *db;
 
-       status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
-       if (status != EFI_BUFFER_TOO_SMALL) {
-               pr_err("Couldn't get size: 0x%lx\n", status);
+       *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+       if (*status == EFI_NOT_FOUND)
+               return NULL;
+
+       if (*status != EFI_BUFFER_TOO_SMALL) {
+               pr_err("Couldn't get size: 0x%lx\n", *status);
                return NULL;
        }
 
@@ -52,10 +54,10 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
        if (!db)
                return NULL;
 
-       status = efi.get_variable(name, guid, NULL, &lsize, db);
-       if (status != EFI_SUCCESS) {
+       *status = efi.get_variable(name, guid, NULL, &lsize, db);
+       if (*status != EFI_SUCCESS) {
                kfree(db);
-               pr_err("Error reading db var: 0x%lx\n", status);
+               pr_err("Error reading db var: 0x%lx\n", *status);
                return NULL;
        }
 
@@ -74,6 +76,7 @@ static int __init load_uefi_certs(void)
        efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
        void *db = NULL, *dbx = NULL, *mok = NULL;
        unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
+       efi_status_t status;
        int rc = 0;
 
        if (!efi.get_variable)
@@ -83,9 +86,12 @@ static int __init load_uefi_certs(void)
         * an error if we can't get them.
         */
        if (!uefi_check_ignore_db()) {
-               db = get_cert_list(L"db", &secure_var, &dbsize);
+               db = get_cert_list(L"db", &secure_var, &dbsize, &status);
                if (!db) {
-                       pr_err("MODSIGN: Couldn't get UEFI db list\n");
+                       if (status == EFI_NOT_FOUND)
+                               pr_debug("MODSIGN: db variable wasn't found\n");
+                       else
+                               pr_err("MODSIGN: Couldn't get UEFI db list\n");
                } else {
                        rc = parse_efi_signature_list("UEFI:db",
                                        db, dbsize, get_handler_for_db);
@@ -96,9 +102,12 @@ static int __init load_uefi_certs(void)
                }
        }
 
-       mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
+       mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
        if (!mok) {
-               pr_info("Couldn't get UEFI MokListRT\n");
+               if (status == EFI_NOT_FOUND)
+                       pr_debug("MokListRT variable wasn't found\n");
+               else
+                       pr_info("Couldn't get UEFI MokListRT\n");
        } else {
                rc = parse_efi_signature_list("UEFI:MokListRT",
                                              mok, moksize, get_handler_for_db);
@@ -107,9 +116,12 @@ static int __init load_uefi_certs(void)
                kfree(mok);
        }
 
-       dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
+       dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);
        if (!dbx) {
-               pr_info("Couldn't get UEFI dbx list\n");
+               if (status == EFI_NOT_FOUND)
+                       pr_debug("dbx variable wasn't found\n");
+               else
+                       pr_info("Couldn't get UEFI dbx list\n");
        } else {
                rc = parse_efi_signature_list("UEFI:dbx",
                                              dbx, dbxsize,
index 6d9592f0ae1d53c42b3d7d59bfdc462f39a34f77..cc93157fa950045b8d74e2fc4a6b1dc4e7753a5d 100644 (file)
@@ -580,7 +580,7 @@ static int update_timestamp_of_queue(struct snd_seq_event *event,
        event->queue = queue;
        event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
        if (real_time) {
-               event->time.time = snd_seq_timer_get_cur_time(q->timer);
+               event->time.time = snd_seq_timer_get_cur_time(q->timer, true);
                event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
        } else {
                event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
@@ -1659,7 +1659,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
        tmr = queue->timer;
        status->events = queue->tickq->cells + queue->timeq->cells;
 
-       status->time = snd_seq_timer_get_cur_time(tmr);
+       status->time = snd_seq_timer_get_cur_time(tmr, true);
        status->tick = snd_seq_timer_get_cur_tick(tmr);
 
        status->running = tmr->running;
index caf68bf42f134be3e802c976b6b824f38d64c82d..71a6ea62c3be7c8a0a1885da0b32b2b527ef8644 100644 (file)
@@ -238,6 +238,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
 {
        unsigned long flags;
        struct snd_seq_event_cell *cell;
+       snd_seq_tick_time_t cur_tick;
+       snd_seq_real_time_t cur_time;
 
        if (q == NULL)
                return;
@@ -254,17 +256,18 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
 
       __again:
        /* Process tick queue... */
+       cur_tick = snd_seq_timer_get_cur_tick(q->timer);
        for (;;) {
-               cell = snd_seq_prioq_cell_out(q->tickq,
-                                             &q->timer->tick.cur_tick);
+               cell = snd_seq_prioq_cell_out(q->tickq, &cur_tick);
                if (!cell)
                        break;
                snd_seq_dispatch_event(cell, atomic, hop);
        }
 
        /* Process time queue... */
+       cur_time = snd_seq_timer_get_cur_time(q->timer, false);
        for (;;) {
-               cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time);
+               cell = snd_seq_prioq_cell_out(q->timeq, &cur_time);
                if (!cell)
                        break;
                snd_seq_dispatch_event(cell, atomic, hop);
@@ -392,6 +395,7 @@ int snd_seq_queue_check_access(int queueid, int client)
 int snd_seq_queue_set_owner(int queueid, int client, int locked)
 {
        struct snd_seq_queue *q = queueptr(queueid);
+       unsigned long flags;
 
        if (q == NULL)
                return -EINVAL;
@@ -401,8 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
                return -EPERM;
        }
 
+       spin_lock_irqsave(&q->owner_lock, flags);
        q->locked = locked ? 1 : 0;
        q->owner = client;
+       spin_unlock_irqrestore(&q->owner_lock, flags);
        queue_access_unlock(q);
        queuefree(q);
 
@@ -539,15 +545,17 @@ void snd_seq_queue_client_termination(int client)
        unsigned long flags;
        int i;
        struct snd_seq_queue *q;
+       bool matched;
 
        for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
                if ((q = queueptr(i)) == NULL)
                        continue;
                spin_lock_irqsave(&q->owner_lock, flags);
-               if (q->owner == client)
+               matched = (q->owner == client);
+               if (matched)
                        q->klocked = 1;
                spin_unlock_irqrestore(&q->owner_lock, flags);
-               if (q->owner == client) {
+               if (matched) {
                        if (q->timer->running)
                                snd_seq_timer_stop(q->timer);
                        snd_seq_timer_reset(q->timer);
@@ -739,6 +747,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
        int i, bpm;
        struct snd_seq_queue *q;
        struct snd_seq_timer *tmr;
+       bool locked;
+       int owner;
 
        for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
                if ((q = queueptr(i)) == NULL)
@@ -750,9 +760,14 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
                else
                        bpm = 0;
 
+               spin_lock_irq(&q->owner_lock);
+               locked = q->locked;
+               owner = q->owner;
+               spin_unlock_irq(&q->owner_lock);
+
                snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name);
-               snd_iprintf(buffer, "owned by client    : %d\n", q->owner);
-               snd_iprintf(buffer, "lock status        : %s\n", q->locked ? "Locked" : "Free");
+               snd_iprintf(buffer, "owned by client    : %d\n", owner);
+               snd_iprintf(buffer, "lock status        : %s\n", locked ? "Locked" : "Free");
                snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq));
                snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq));
                snd_iprintf(buffer, "timer state        : %s\n", tmr->running ? "Running" : "Stopped");
index be59b59c9be40c233995817f3ddb3e5d71fbb6d7..1645e4142e30246dc30af69857d1dc8e9f736219 100644 (file)
@@ -428,14 +428,15 @@ int snd_seq_timer_continue(struct snd_seq_timer *tmr)
 }
 
 /* return current 'real' time. use timeofday() to get better granularity. */
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
+                                              bool adjust_ktime)
 {
        snd_seq_real_time_t cur_time;
        unsigned long flags;
 
        spin_lock_irqsave(&tmr->lock, flags);
        cur_time = tmr->cur_time;
-       if (tmr->running) { 
+       if (adjust_ktime && tmr->running) {
                struct timespec64 tm;
 
                ktime_get_ts64(&tm);
@@ -452,7 +453,13 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
  high PPQ values) */
 snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
 {
-       return tmr->tick.cur_tick;
+       snd_seq_tick_time_t cur_tick;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tmr->lock, flags);
+       cur_tick = tmr->tick.cur_tick;
+       spin_unlock_irqrestore(&tmr->lock, flags);
+       return cur_tick;
 }
 
 
index 66c3e344eae37f9285e90ab3b8d607f6d1f4bb02..4bec57df8158caf81e6cdba3248d7e252bd34643 100644 (file)
@@ -120,7 +120,8 @@ int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
 int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
 int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr);
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
+                                              bool adjust_ktime);
 snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
 
 extern int seq_default_timer_class;
index a684f0520b4b982f71897967641d05ce0dca5128..4d060d5b1db6dc7eabfd5d44c3ef965792925537 100644 (file)
@@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);
 int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
                                struct hdac_ext_link *link)
 {
+       unsigned long codec_mask;
        int ret = 0;
 
        mutex_lock(&bus->lock);
@@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
                 *  HDA spec section 4.3 - Codec Discovery
                 */
                udelay(521);
-               bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
-               dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
-               snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask);
+               codec_mask = snd_hdac_chip_readw(bus, STATESTS);
+               dev_dbg(bus->dev, "codec_mask = 0x%lx\n", codec_mask);
+               snd_hdac_chip_writew(bus, STATESTS, codec_mask);
+               if (!bus->codec_mask)
+                       bus->codec_mask = codec_mask;
        }
 
        mutex_unlock(&bus->lock);
index 5fd6d575e123b0e4cb20a986ecf8010d1795023c..aad5c4bf4d3441754b0ec1d5d046b438b1ee6c5e 100644 (file)
@@ -250,7 +250,7 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
                if (spk_alloc & (1 << i))
-                       j += snprintf(buf + j, buflen - j,  " %s",
+                       j += scnprintf(buf + j, buflen - j,  " %s",
                                        cea_speaker_allocation_names[i]);
        }
        buf[j] = '\0';  /* necessary when j == 0 */
index 5dc42f932739f3b385f826cb4431e0ed85731a0f..53e7732ef75209b63617ecc700c55cf994064bf8 100644 (file)
@@ -4022,7 +4022,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
                if (pcm & (AC_SUPPCM_BITS_8 << i))
-                       j += snprintf(buf + j, buflen - j,  " %d", bits[i]);
+                       j += scnprintf(buf + j, buflen - j,  " %d", bits[i]);
 
        buf[j] = '\0'; /* necessary when j == 0 */
 }
index bb46c89b7f63d9c06e8500065170bbabbc8205e7..136477ed46ae2673db07fcd200b61871063dab07 100644 (file)
@@ -360,7 +360,7 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
                if (pcm & (1 << i))
-                       j += snprintf(buf + j, buflen - j,  " %d",
+                       j += scnprintf(buf + j, buflen - j,  " %d",
                                alsa_rates[i]);
 
        buf[j] = '\0'; /* necessary when j == 0 */
index 0607ed5d1959958da12647ba6b4b165c5683d4da..eb8ec109d7adb5ce187567b2a5a8c10bdc3eec05 100644 (file)
@@ -222,7 +222,7 @@ static ssize_t init_verbs_show(struct device *dev,
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
        snd_array_for_each(&codec->init_verbs, i, v) {
-               len += snprintf(buf + len, PAGE_SIZE - len,
+               len += scnprintf(buf + len, PAGE_SIZE - len,
                                "0x%02x 0x%03x 0x%04x\n",
                                v->nid, v->verb, v->param);
        }
@@ -272,7 +272,7 @@ static ssize_t hints_show(struct device *dev,
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
        snd_array_for_each(&codec->hints, i, hint) {
-               len += snprintf(buf + len, PAGE_SIZE - len,
+               len += scnprintf(buf + len, PAGE_SIZE - len,
                                "%s = %s\n", hint->key, hint->val);
        }
        mutex_unlock(&codec->user_mutex);
index 6c8cb4ce517eb6539ea6fc78b16e7b03ed0fe5bd..477589e7ec1d90b8346542c3dd8cf8bd57b9063f 100644 (file)
@@ -2447,7 +2447,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
index 31cd4008e33ff88d9b61085133d12755a60f1724..91a388184e525d66f0953effc36f0b6204a04972 100644 (file)
@@ -170,6 +170,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
        struct snd_soc_card *card;
        struct acp3x_platform_info *pinfo;
        u32 ret, val, period_bytes, reg_val, ier_val, water_val;
+       u32 buf_size, buf_reg;
 
        prtd = substream->private_data;
        rtd = substream->runtime->private_data;
@@ -183,6 +184,8 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
        }
        period_bytes = frames_to_bytes(substream->runtime,
                        substream->runtime->period_size);
+       buf_size = frames_to_bytes(substream->runtime,
+                       substream->runtime->buffer_size);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
@@ -196,6 +199,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_BT_TX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_BTTDM_ITER;
                                ier_val = mmACP_BTTDM_IER;
+                               buf_reg = mmACP_BT_TX_RINGBUFSIZE;
                                break;
                        case I2S_SP_INSTANCE:
                        default:
@@ -203,6 +207,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_I2S_TX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_I2STDM_ITER;
                                ier_val = mmACP_I2STDM_IER;
+                               buf_reg = mmACP_I2S_TX_RINGBUFSIZE;
                        }
                } else {
                        switch (rtd->i2s_instance) {
@@ -211,6 +216,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_BT_RX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_BTTDM_IRER;
                                ier_val = mmACP_BTTDM_IER;
+                               buf_reg = mmACP_BT_RX_RINGBUFSIZE;
                                break;
                        case I2S_SP_INSTANCE:
                        default:
@@ -218,9 +224,11 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_I2S_RX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_I2STDM_IRER;
                                ier_val = mmACP_I2STDM_IER;
+                               buf_reg = mmACP_I2S_RX_RINGBUFSIZE;
                        }
                }
                rv_writel(period_bytes, rtd->acp3x_base + water_val);
+               rv_writel(buf_size, rtd->acp3x_base + buf_reg);
                val = rv_readl(rtd->acp3x_base + reg_val);
                val = val | BIT(0);
                rv_writel(val, rtd->acp3x_base + reg_val);
index aecc3c06167907a00634559a25dea93c04fa0f8a..d62c0d90c41e34d99421f840312c8c77c04c793b 100644 (file)
@@ -110,7 +110,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 {
        u16 page_idx;
        u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
-       u32 reg_ringbuf_size, reg_dma_size, reg_fifo_size;
+       u32 reg_dma_size, reg_fifo_size;
        dma_addr_t addr;
 
        addr = rtd->dma_addr;
@@ -157,7 +157,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                switch (rtd->i2s_instance) {
                case I2S_BT_INSTANCE:
-                       reg_ringbuf_size = mmACP_BT_TX_RINGBUFSIZE;
                        reg_dma_size = mmACP_BT_TX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                BT_PB_FIFO_ADDR_OFFSET;
@@ -169,7 +168,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
                case I2S_SP_INSTANCE:
                default:
-                       reg_ringbuf_size = mmACP_I2S_TX_RINGBUFSIZE;
                        reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                SP_PB_FIFO_ADDR_OFFSET;
@@ -181,7 +179,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
        } else {
                switch (rtd->i2s_instance) {
                case I2S_BT_INSTANCE:
-                       reg_ringbuf_size = mmACP_BT_RX_RINGBUFSIZE;
                        reg_dma_size = mmACP_BT_RX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                BT_CAPT_FIFO_ADDR_OFFSET;
@@ -193,7 +190,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
                case I2S_SP_INSTANCE:
                default:
-                       reg_ringbuf_size = mmACP_I2S_RX_RINGBUFSIZE;
                        reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                SP_CAPT_FIFO_ADDR_OFFSET;
@@ -203,7 +199,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
                                rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
                }
        }
-       rv_writel(MAX_BUFFER, rtd->acp3x_base + reg_ringbuf_size);
        rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
        rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
        rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
index 65330bb50e74c991e8b0abed3d7e584a10785e15..da60e2ec5535172710229db1d461bff899a965b1 100644 (file)
@@ -45,23 +45,6 @@ static int acp3x_power_on(void __iomem *acp3x_base)
        return -ETIMEDOUT;
 }
 
-static int acp3x_power_off(void __iomem *acp3x_base)
-{
-       u32 val;
-       int timeout;
-
-       rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
-                       acp3x_base + mmACP_PGFSM_CONTROL);
-       timeout = 0;
-       while (++timeout < 500) {
-               val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
-               if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
-                       return 0;
-               udelay(1);
-       }
-       return -ETIMEDOUT;
-}
-
 static int acp3x_reset(void __iomem *acp3x_base)
 {
        u32 val;
@@ -115,12 +98,6 @@ static int acp3x_deinit(void __iomem *acp3x_base)
                pr_err("ACP3x reset failed\n");
                return ret;
        }
-       /* power off */
-       ret = acp3x_power_off(acp3x_base);
-       if (ret) {
-               pr_err("ACP3x power off failed\n");
-               return ret;
-       }
        return 0;
 }
 
index d1dc8e6366dcbd3356cb39dafb2cc41753bd4896..71f2d42188c461a4169af85cac84511851f122ac 100644 (file)
@@ -10,11 +10,11 @@ config SND_ATMEL_SOC
 if SND_ATMEL_SOC
 
 config SND_ATMEL_SOC_PDC
-       tristate
+       bool
        depends on HAS_DMA
 
 config SND_ATMEL_SOC_DMA
-       tristate
+       bool
        select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_ATMEL_SOC_SSC
index 1f6890ed373826fbad9432df6e6c14eebb2924b7..c7d2989791be1a2db9f4100246d8414ecea67d68 100644 (file)
@@ -6,8 +6,14 @@ snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
 
-obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
-obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
+# pdc and dma need to both be built-in if any user of
+# ssc is built-in.
+ifdef CONFIG_SND_ATMEL_SOC_PDC
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-pdc.o
+endif
+ifdef CONFIG_SND_ATMEL_SOC_DMA
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-dma.o
+endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
index 444cc4e3374e17eb8b0dc988664d0d04914b3025..f005751da2ccb39abd42adb029c0f5fa0e4e3eac 100644 (file)
@@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
        return ret;
 }
 
+static void hdmi_remove(struct snd_soc_component *component)
+{
+       struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+
+       if (hcp->hcd.ops->hook_plugged_cb)
+               hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+                                             hcp->hcd.data, NULL, NULL);
+}
+
 static const struct snd_soc_component_driver hdmi_driver = {
+       .remove                 = hdmi_remove,
        .dapm_widgets           = hdmi_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
        .of_xlate_dai_id        = hdmi_of_xlate_dai_id,
index 5bc2c6411b33bfbd4747a6b836375039bfdc1885..032adc14562d24c54b4933c0c4818f0537ebb1f4 100644 (file)
  * Copyright 2011-2012 Maxim Integrated Products
  */
 
-#include <linux/acpi.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/clk.h>
 #include <sound/jack.h>
-#include <sound/max98090.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <sound/max98090.h>
 #include "max98090.h"
 
-static void max98090_shdn_save_locked(struct max98090_priv *max98090)
-{
-       int shdn = 0;
-
-       /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
-       regmap_read(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, &shdn);
-       max98090->saved_shdn |= shdn;
-       ++max98090->saved_count;
-
-       if (shdn)
-               regmap_write(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, 0x0);
-}
-
-static void max98090_shdn_restore_locked(struct max98090_priv *max98090)
-{
-       /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
-       if (--max98090->saved_count == 0) {
-               if (max98090->saved_shdn) {
-                       regmap_write(max98090->regmap,
-                                    M98090_REG_DEVICE_SHUTDOWN,
-                                    M98090_SHDNN_MASK);
-                       max98090->saved_shdn = 0;
-               }
-       }
-}
-
-static void max98090_shdn_save(struct max98090_priv *max98090)
-{
-       mutex_lock_nested(&max98090->component->card->dapm_mutex,
-                         SND_SOC_DAPM_CLASS_RUNTIME);
-       max98090_shdn_save_locked(max98090);
-}
-
-static void max98090_shdn_restore(struct max98090_priv *max98090)
-{
-       max98090_shdn_restore_locked(max98090);
-       mutex_unlock(&max98090->component->card->dapm_mutex);
-}
-
-static int max98090_put_volsw(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_put_volsw(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_dapm_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_dapm_put_enum_double_locked(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_put_enum_double(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_bytes_put(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_bytes_put(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_dapm_event(struct snd_soc_dapm_widget *w,
-       struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_component *component =
-               snd_soc_dapm_to_component(w->dapm);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-       case SND_SOC_DAPM_PRE_PMD:
-               max98090_shdn_save_locked(max98090);
-               break;
-       case SND_SOC_DAPM_POST_PMU:
-       case SND_SOC_DAPM_POST_PMD:
-               max98090_shdn_restore_locked(max98090);
-               break;
-       }
-
-       return 0;
-}
-
 /* Allows for sparsely populated register maps */
 static const struct reg_default max98090_reg[] = {
        { 0x00, 0x00 }, /* 00 Software Reset */
@@ -632,13 +506,10 @@ static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
                            max98090_pwr_perf_text);
 
 static const struct snd_kcontrol_new max98090_snd_controls[] = {
-       SOC_ENUM_EXT("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
 
-       SOC_SINGLE_EXT("DMIC MIC Comp Filter Config",
-               M98090_REG_DIGITAL_MIC_CONFIG,
-               M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_SINGLE("DMIC MIC Comp Filter Config", M98090_REG_DIGITAL_MIC_CONFIG,
+               M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0),
 
        SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
                M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
@@ -693,34 +564,24 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
                M98090_AVR_SHIFT, M98090_AVR_NUM - 1, 1,
                max98090_av_tlv),
 
-       SOC_ENUM_EXT("ADC Oversampling Rate", max98090_osr128_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
-               M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("ADC High Performance Mode", max98090_adchp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-
-       SOC_SINGLE_EXT("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDIN Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("Filter Mode", max98090_mode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
-               M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
-               M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_ENUM("ADC Oversampling Rate", max98090_osr128_enum),
+       SOC_SINGLE("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
+               M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0),
+       SOC_ENUM("ADC High Performance Mode", max98090_adchp_enum),
+
+       SOC_SINGLE("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0),
+       SOC_SINGLE("SDIN Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0),
+       SOC_SINGLE("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0),
+       SOC_SINGLE("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1),
+       SOC_ENUM("Filter Mode", max98090_mode_enum),
+       SOC_SINGLE("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
+               M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0),
+       SOC_SINGLE("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
+               M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0),
        SOC_SINGLE_TLV("Digital BQ Volume", M98090_REG_ADC_BIQUAD_LEVEL,
                M98090_AVBQ_SHIFT, M98090_AVBQ_NUM - 1, 1, max98090_dv_tlv),
        SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
@@ -733,17 +594,13 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
        SOC_SINGLE_TLV("Digital Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
                M98090_DV_SHIFT, M98090_DV_NUM - 1, 1,
                max98090_dv_tlv),
-       SND_SOC_BYTES_E("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105,
-               snd_soc_bytes_get, max98090_bytes_put),
-       SOC_SINGLE_EXT("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SND_SOC_BYTES("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105),
+       SOC_SINGLE("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0),
+       SOC_SINGLE("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0),
+       SOC_SINGLE("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0),
        SOC_SINGLE("Digital EQ Clipping Detection", M98090_REG_DAI_PLAYBACK_LEVEL_EQ,
                M98090_EQCLPN_SHIFT, M98090_EQCLPN_NUM - 1,
                1),
@@ -751,34 +608,25 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
                M98090_DVEQ_SHIFT, M98090_DVEQ_NUM - 1, 1,
                max98090_dv_tlv),
 
-       SOC_SINGLE_EXT("ALC Enable", M98090_REG_DRC_TIMING,
-               M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("ALC Attack Time", max98090_drcatk_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("ALC Release Time", max98090_drcrls_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_SINGLE("ALC Enable", M98090_REG_DRC_TIMING,
+               M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0),
+       SOC_ENUM("ALC Attack Time", max98090_drcatk_enum),
+       SOC_ENUM("ALC Release Time", max98090_drcrls_enum),
        SOC_SINGLE_TLV("ALC Make Up Volume", M98090_REG_DRC_GAIN,
                M98090_DRCG_SHIFT, M98090_DRCG_NUM - 1, 0,
                max98090_alcmakeup_tlv),
-       SOC_ENUM_EXT("ALC Compression Ratio", max98090_alccmp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("ALC Expansion Ratio", max98090_drcexp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT_TLV("ALC Compression Threshold Volume",
+       SOC_ENUM("ALC Compression Ratio", max98090_alccmp_enum),
+       SOC_ENUM("ALC Expansion Ratio", max98090_drcexp_enum),
+       SOC_SINGLE_TLV("ALC Compression Threshold Volume",
                M98090_REG_DRC_COMPRESSOR, M98090_DRCTHC_SHIFT,
-               M98090_DRCTHC_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw, max98090_alccomp_tlv),
-       SOC_SINGLE_EXT_TLV("ALC Expansion Threshold Volume",
+               M98090_DRCTHC_NUM - 1, 1, max98090_alccomp_tlv),
+       SOC_SINGLE_TLV("ALC Expansion Threshold Volume",
                M98090_REG_DRC_EXPANDER, M98090_DRCTHE_SHIFT,
-               M98090_DRCTHE_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw, max98090_drcexp_tlv),
+               M98090_DRCTHE_NUM - 1, 1, max98090_drcexp_tlv),
 
-       SOC_ENUM_EXT("DAC HP Playback Performance Mode",
-               max98090_dac_perfmode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("DAC High Performance Mode", max98090_dachp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_ENUM("DAC HP Playback Performance Mode",
+               max98090_dac_perfmode_enum),
+       SOC_ENUM("DAC High Performance Mode", max98090_dachp_enum),
 
        SOC_SINGLE_TLV("Headphone Left Mixer Volume",
                M98090_REG_HP_CONTROL, M98090_MIXHPLG_SHIFT,
@@ -836,12 +684,9 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
        SOC_SINGLE("Volume Adjustment Smoothing", M98090_REG_LEVEL_CONTROL,
                M98090_VSENN_SHIFT, M98090_VSENN_NUM - 1, 1),
 
-       SND_SOC_BYTES_E("Biquad Coefficients",
-               M98090_REG_RECORD_BIQUAD_BASE, 15,
-               snd_soc_bytes_get, max98090_bytes_put),
-       SOC_SINGLE_EXT("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SND_SOC_BYTES("Biquad Coefficients", M98090_REG_RECORD_BIQUAD_BASE, 15),
+       SOC_SINGLE("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0),
 };
 
 static const struct snd_kcontrol_new max98091_snd_controls[] = {
@@ -850,12 +695,10 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
                M98090_DMIC34_ZEROPAD_SHIFT,
                M98090_DMIC34_ZEROPAD_NUM - 1, 0),
 
-       SOC_ENUM_EXT("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
+       SOC_ENUM("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum),
+       SOC_SINGLE("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
                M98090_FLT_DMIC34HPF_SHIFT,
-               M98090_FLT_DMIC34HPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+               M98090_FLT_DMIC34HPF_NUM - 1, 0),
 
        SOC_SINGLE_TLV("DMIC3 Boost Volume", M98090_REG_DMIC3_VOLUME,
                M98090_DMIC_AV3G_SHIFT, M98090_DMIC_AV3G_NUM - 1, 0,
@@ -873,9 +716,8 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
 
        SND_SOC_BYTES("DMIC34 Biquad Coefficients",
                M98090_REG_DMIC34_BIQUAD_BASE, 15),
-       SOC_SINGLE_EXT("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_SINGLE("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0),
 
        SOC_SINGLE_TLV("DMIC34 BQ PreAttenuation Volume",
                M98090_REG_DMIC34_BQ_PREATTEN, M98090_AV34BQ_SHIFT,
@@ -929,6 +771,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int max98090_shdn_event(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+       struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
+
+       if (event & SND_SOC_DAPM_POST_PMU)
+               max98090->shdn_pending = true;
+
+       return 0;
+
+}
+
 static const char *mic1_mux_text[] = { "IN12", "IN56" };
 
 static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
@@ -1029,14 +884,10 @@ static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
                            lten_mux_text);
 
 static const struct snd_kcontrol_new max98090_ltenl_mux =
-       SOC_DAPM_ENUM_EXT("LTENL Mux", ltenl_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
 
 static const struct snd_kcontrol_new max98090_ltenr_mux =
-       SOC_DAPM_ENUM_EXT("LTENR Mux", ltenr_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LTENR Mux", ltenr_mux_enum);
 
 static const char *lben_mux_text[] = { "Normal", "Loopback" };
 
@@ -1051,14 +902,10 @@ static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
                            lben_mux_text);
 
 static const struct snd_kcontrol_new max98090_lbenl_mux =
-       SOC_DAPM_ENUM_EXT("LBENL Mux", lbenl_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
 
 static const struct snd_kcontrol_new max98090_lbenr_mux =
-       SOC_DAPM_ENUM_EXT("LBENR Mux", lbenr_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LBENR Mux", lbenr_mux_enum);
 
 static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
 
@@ -1225,25 +1072,21 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("IN56"),
 
        SND_SOC_DAPM_SUPPLY("MICBIAS", M98090_REG_INPUT_ENABLE,
-               M98090_MBEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_MBEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SHDN", M98090_REG_DEVICE_SHUTDOWN,
                M98090_SHDNN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SDIEN", M98090_REG_IO_CONFIGURATION,
-               M98090_SDIEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_SDIEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION,
-               M98090_SDOEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_SDOEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMICL_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMICL_SHIFT, 0, max98090_shdn_event,
+                       SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMICR_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMICR_SHIFT, 0, max98090_shdn_event,
+                        SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG,
-               M98090_AHPF_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_AHPF_SHIFT, 0, NULL, 0),
 
 /*
  * Note: Sysclk and misc power supplies are taken care of by SHDN
@@ -1273,12 +1116,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
                &max98090_lineb_mixer_controls[0],
                ARRAY_SIZE(max98090_lineb_mixer_controls)),
 
-       SND_SOC_DAPM_PGA_E("LINEA Input", M98090_REG_INPUT_ENABLE,
-               M98090_LINEAEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("LINEB Input", M98090_REG_INPUT_ENABLE,
-               M98090_LINEBEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_PGA("LINEA Input", M98090_REG_INPUT_ENABLE,
+               M98090_LINEAEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LINEB Input", M98090_REG_INPUT_ENABLE,
+               M98090_LINEBEN_SHIFT, 0, NULL, 0),
 
        SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
                &max98090_left_adc_mixer_controls[0],
@@ -1289,11 +1130,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
                ARRAY_SIZE(max98090_right_adc_mixer_controls)),
 
        SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE,
-               M98090_ADLEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_ADLEN_SHIFT, 0, max98090_shdn_event,
+               SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE,
-               M98090_ADREN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_ADREN_SHIFT, 0, max98090_shdn_event,
+               SND_SOC_DAPM_POST_PMU),
 
        SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0,
                SND_SOC_NOPM, 0, 0),
@@ -1321,12 +1162,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0),
 
-       SND_SOC_DAPM_DAC_E("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
-               M98090_DALEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_DAC_E("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
-               M98090_DAREN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_DAC("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
+               M98090_DALEN_SHIFT, 0),
+       SND_SOC_DAPM_DAC("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
+               M98090_DAREN_SHIFT, 0),
 
        SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
                &max98090_left_hp_mixer_controls[0],
@@ -1361,26 +1200,20 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("MIXHPRSEL Mux", SND_SOC_NOPM, 0, 0,
                &max98090_mixhprsel_mux),
 
-       SND_SOC_DAPM_PGA_E("HP Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_HPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("HP Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_HPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-
-       SND_SOC_DAPM_PGA_E("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_SPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_SPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-
-       SND_SOC_DAPM_PGA_E("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_RCVLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_RCVREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_PGA("HP Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_HPLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HP Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_HPREN_SHIFT, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_SPLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_SPREN_SHIFT, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_RCVLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_RCVREN_SHIFT, 0, NULL, 0),
 
        SND_SOC_DAPM_OUTPUT("HPL"),
        SND_SOC_DAPM_OUTPUT("HPR"),
@@ -1395,11 +1228,9 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("DMIC4"),
 
        SND_SOC_DAPM_SUPPLY("DMIC3_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMIC3_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMIC3_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("DMIC4_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMIC4_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMIC4_SHIFT, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
@@ -1670,11 +1501,6 @@ static void max98090_configure_bclk(struct snd_soc_component *component)
                return;
        }
 
-       /*
-        * Master mode: no need to save and restore SHDN for the following
-        * sensitive registers.
-        */
-
        /* Check for supported PCLK to LRCLK ratios */
        for (i = 0; i < ARRAY_SIZE(pclk_rates); i++) {
                if ((pclk_rates[i] == max98090->sysclk) &&
@@ -1761,14 +1587,12 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
                case SND_SOC_DAIFMT_CBS_CFS:
                        /* Set to slave mode PLL - MAS mode off */
-                       max98090_shdn_save(max98090);
                        snd_soc_component_write(component,
                                M98090_REG_CLOCK_RATIO_NI_MSB, 0x00);
                        snd_soc_component_write(component,
                                M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
                        snd_soc_component_update_bits(component, M98090_REG_CLOCK_MODE,
                                M98090_USE_M1_MASK, 0);
-                       max98090_shdn_restore(max98090);
                        max98090->master = false;
                        break;
                case SND_SOC_DAIFMT_CBM_CFM:
@@ -1794,9 +1618,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                        dev_err(component->dev, "DAI clock mode unsupported");
                        return -EINVAL;
                }
-               max98090_shdn_save(max98090);
                snd_soc_component_write(component, M98090_REG_MASTER_MODE, regval);
-               max98090_shdn_restore(max98090);
 
                regval = 0;
                switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1841,10 +1663,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                if (max98090->tdm_slots > 1)
                        regval ^= M98090_BCI_MASK;
 
-               max98090_shdn_save(max98090);
                snd_soc_component_write(component,
                        M98090_REG_INTERFACE_FORMAT, regval);
-               max98090_shdn_restore(max98090);
        }
 
        return 0;
@@ -1856,7 +1676,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
        struct snd_soc_component *component = codec_dai->component;
        struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
        struct max98090_cdata *cdata;
-
        cdata = &max98090->dai[0];
 
        if (slots < 0 || slots > 4)
@@ -1866,7 +1685,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
        max98090->tdm_width = slot_width;
 
        if (max98090->tdm_slots > 1) {
-               max98090_shdn_save(max98090);
                /* SLOTL SLOTR SLOTDLY */
                snd_soc_component_write(component, M98090_REG_TDM_FORMAT,
                        0 << M98090_TDM_SLOTL_SHIFT |
@@ -1877,7 +1695,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
                snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL,
                        M98090_TDM_MASK,
                        M98090_TDM_MASK);
-               max98090_shdn_restore(max98090);
        }
 
        /*
@@ -2077,7 +1894,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
        dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq;
        dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i];
 
-       max98090_shdn_save(max98090);
        regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE,
                           M98090_MICCLK_MASK,
                           micclk_index << M98090_MICCLK_SHIFT);
@@ -2086,7 +1902,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
                           M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK,
                           dmic_comp << M98090_DMIC_COMP_SHIFT |
                           dmic_freq << M98090_DMIC_FREQ_SHIFT);
-       max98090_shdn_restore(max98090);
 
        return 0;
 }
@@ -2123,10 +1938,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
 
        switch (params_width(params)) {
        case 16:
-               max98090_shdn_save(max98090);
                snd_soc_component_update_bits(component, M98090_REG_INTERFACE_FORMAT,
                        M98090_WS_MASK, 0);
-               max98090_shdn_restore(max98090);
                break;
        default:
                return -EINVAL;
@@ -2137,7 +1950,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
 
        cdata->rate = max98090->lrclk;
 
-       max98090_shdn_save(max98090);
        /* Update filter mode */
        if (max98090->lrclk < 24000)
                snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
@@ -2153,7 +1965,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
        else
                snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
                        M98090_DHF_MASK, M98090_DHF_MASK);
-       max98090_shdn_restore(max98090);
 
        max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk,
                                max98090->lrclk);
@@ -2184,7 +1995,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
         *               0x02 (when master clk is 20MHz to 40MHz)..
         *               0x03 (when master clk is 40MHz to 60MHz)..
         */
-       max98090_shdn_save(max98090);
        if ((freq >= 10000000) && (freq <= 20000000)) {
                snd_soc_component_write(component, M98090_REG_SYSTEM_CLOCK,
                        M98090_PSCLK_DIV1);
@@ -2199,10 +2009,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
                max98090->pclk = freq >> 2;
        } else {
                dev_err(component->dev, "Invalid master clock frequency\n");
-               max98090_shdn_restore(max98090);
                return -EINVAL;
        }
-       max98090_shdn_restore(max98090);
 
        max98090->sysclk = freq;
 
@@ -2314,12 +2122,10 @@ static void max98090_pll_work(struct max98090_priv *max98090)
         */
 
        /* Toggle shutdown OFF then ON */
-       mutex_lock(&component->card->dapm_mutex);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, 0);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, M98090_SHDNN_MASK);
-       mutex_unlock(&component->card->dapm_mutex);
 
        for (i = 0; i < 10; ++i) {
                /* Give PLL time to lock */
@@ -2642,12 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component)
         */
        snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS);
 
-       /*
-        * SHDN should be 0 at the point, no need to save/restore for the
-        * following registers.
-        *
-        * High Performance is default
-        */
+       /* High Performance is default */
        snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL,
                M98090_DACHP_MASK,
                1 << M98090_DACHP_SHIFT);
@@ -2658,12 +2459,7 @@ static int max98090_probe(struct snd_soc_component *component)
                M98090_ADCHP_MASK,
                1 << M98090_ADCHP_SHIFT);
 
-       /*
-        * SHDN should be 0 at the point, no need to save/restore for the
-        * following registers.
-        *
-        * Turn on VCM bandgap reference
-        */
+       /* Turn on VCM bandgap reference */
        snd_soc_component_write(component, M98090_REG_BIAS_CONTROL,
                M98090_VCM_MODE_MASK);
 
@@ -2695,9 +2491,25 @@ static void max98090_remove(struct snd_soc_component *component)
        max98090->component = NULL;
 }
 
+static void max98090_seq_notifier(struct snd_soc_component *component,
+       enum snd_soc_dapm_type event, int subseq)
+{
+       struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
+
+       if (max98090->shdn_pending) {
+               snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
+                               M98090_SHDNN_MASK, 0);
+               msleep(40);
+               snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
+                               M98090_SHDNN_MASK, M98090_SHDNN_MASK);
+               max98090->shdn_pending = false;
+       }
+}
+
 static const struct snd_soc_component_driver soc_component_dev_max98090 = {
        .probe                  = max98090_probe,
        .remove                 = max98090_remove,
+       .seq_notifier           = max98090_seq_notifier,
        .set_bias_level         = max98090_set_bias_level,
        .idle_bias_on           = 1,
        .use_pmdown_time        = 1,
index 0a31708b7df7f7ad19083d360e4b23fb347c610c..a197114b0dad3fc648952b8f272fb8b87c1a77c1 100644 (file)
@@ -1539,8 +1539,7 @@ struct max98090_priv {
        unsigned int pa2en;
        unsigned int sidetone;
        bool master;
-       int saved_count;
-       int saved_shdn;
+       bool shdn_pending;
 };
 
 int max98090_mic_detect(struct snd_soc_component *component,
index 8c3ea73009721f8fb89c8e4d54ca47b8b0fb50a8..9d436b0c5718a2531049e7e8ba7d025b6f1fe4c6 100644 (file)
@@ -1020,12 +1020,24 @@ static int fsl_sai_probe(struct platform_device *pdev)
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
                        &fsl_sai_dai, 1);
        if (ret)
-               return ret;
+               goto err_pm_disable;
 
-       if (sai->soc_data->use_imx_pcm)
-               return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
-       else
-               return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (sai->soc_data->use_imx_pcm) {
+               ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
+               if (ret)
+                       goto err_pm_disable;
+       } else {
+               ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+               if (ret)
+                       goto err_pm_disable;
+       }
+
+       return ret;
+
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+
+       return ret;
 }
 
 static int fsl_sai_remove(struct platform_device *pdev)
index bc20ad9abf8bddc119381f1ddbf010b766f7fc8d..9b130561d562f8bec717b9511ec08618a987aa4e 100644 (file)
@@ -3441,8 +3441,17 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 
-static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol, int locked)
+/**
+ * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a dapm enumerated double mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
        struct snd_soc_card *card = dapm->card;
@@ -3465,9 +3474,7 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                mask |= e->mask << e->shift_r;
        }
 
-       if (!locked)
-               mutex_lock_nested(&card->dapm_mutex,
-                                 SND_SOC_DAPM_CLASS_RUNTIME);
+       mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
        change = dapm_kcontrol_set_value(kcontrol, val);
 
@@ -3489,50 +3496,15 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                card->update = NULL;
        }
 
-       if (!locked)
-               mutex_unlock(&card->dapm_mutex);
+       mutex_unlock(&card->dapm_mutex);
 
        if (ret > 0)
                soc_dpcm_runtime_update(card);
 
        return change;
 }
-
-/**
- * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a dapm enumerated double mixer control.
- *
- * Returns 0 for success.
- */
-int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 0);
-}
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
 
-/**
- * snd_soc_dapm_put_enum_double_locked - dapm enumerated double mixer set
- * callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a dapm enumerated double mixer control.
- * Must acquire dapm_mutex before calling the function.
- *
- * Returns 0 for success.
- */
-int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       dapm_assert_locked(snd_soc_dapm_kcontrol_dapm(kcontrol));
-       return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 1);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double_locked);
-
 /**
  * snd_soc_dapm_info_pin_switch - Info for a pin switch
  *
@@ -3916,9 +3888,6 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,
        runtime->rate = params_rate(params);
 
 out:
-       if (ret < 0)
-               kfree(runtime);
-
        kfree(params);
        return ret;
 }
index 9106ab8dac6f62d6efc0251c5b26770ff1e856fb..ff45075ef7203809acb355a6f6c6b028e9daf94f 100644 (file)
@@ -174,8 +174,10 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
 
-       dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
-       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
+       if (HDA_IDISP_CODEC(bus->codec_mask)) {
+               dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
+       }
 }
 EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
 
@@ -189,7 +191,8 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev)
        if (ret < 0)
                return ret;
 
-       hda_codec_i915_display_power(sdev, true);
+       /* codec_mask not yet known, power up for probe */
+       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 
        return 0;
 }
@@ -200,7 +203,8 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
        struct hdac_bus *bus = sof_to_bus(sdev);
        int ret;
 
-       hda_codec_i915_display_power(sdev, false);
+       /* power down unconditionally */
+       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 
        ret = snd_hdac_i915_exit(bus);
 
index 4a4d318f97ffa5698217c0282bb24321f94d4b4b..0848b79967a9f426e4c7d6124906eb51fe25bed9 100644 (file)
@@ -428,6 +428,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
                return ret;
        }
 
+       /* display codec can powered off after link reset */
+       hda_codec_i915_display_power(sdev, false);
+
        return 0;
 }
 
@@ -439,6 +442,9 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
 #endif
        int ret;
 
+       /* display codec must be powered before link reset */
+       hda_codec_i915_display_power(sdev, true);
+
        /*
         * clear TCSEL to clear playback on some HD Audio
         * codecs. PCI TCSEL is defined in the Intel manuals.
@@ -482,6 +488,8 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
        struct pci_dev *pci = to_pci_dev(sdev->dev);
 
        if (sdev->s0_suspend) {
+               hda_codec_i915_display_power(sdev, true);
+
                /* restore L1SEN bit */
                if (hda->l1_support_changed)
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
@@ -531,6 +539,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev)
        int ret;
 
        if (sdev->s0_suspend) {
+               /* we can't keep a wakeref to display driver at suspend */
+               hda_codec_i915_display_power(sdev, false);
+
                /* enable L1SEN to make sure the system can enter S0Ix */
                hda->l1_support_changed =
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
index 65b86dd044f101b0255c9be51d01961469e37407..25946a1c28224c69e2925a4b477a854769e47d62 100644 (file)
@@ -286,6 +286,13 @@ static int hda_init(struct snd_sof_dev *sdev)
        /* HDA base */
        sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr;
 
+       /* init i915 and HDMI codecs */
+       ret = hda_codec_i915_init(sdev);
+       if (ret < 0) {
+               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
+               return ret;
+       }
+
        /* get controller capabilities */
        ret = hda_dsp_ctrl_get_caps(sdev);
        if (ret < 0)
@@ -353,15 +360,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        if (bus->ppcap)
                dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-       /* init i915 and HDMI codecs */
-       ret = hda_codec_i915_init(sdev);
-       if (ret < 0) {
-               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
-               return ret;
-       }
-#endif
-
        /* Init HDA controller after i915 init */
        ret = hda_dsp_ctrl_init_chip(sdev, true);
        if (ret < 0) {
@@ -381,7 +379,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
 
        if (!HDA_IDISP_CODEC(bus->codec_mask))
-               hda_codec_i915_display_power(sdev, false);
+               hda_codec_i915_exit(sdev);
 
        /*
         * we are done probing so decrement link counts
@@ -611,6 +609,7 @@ free_streams:
        iounmap(sdev->bar[HDA_DSP_BAR]);
 hdac_bus_unmap:
        iounmap(bus->remap_addr);
+       hda_codec_i915_exit(sdev);
 err:
        return ret;
 }
index 55798bc8eae29d27c9b85d548b4fb8d8ef355ecc..686561df8e13b30ef1672d7b7aa3c80926e7e479 100644 (file)
@@ -80,6 +80,7 @@
 
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK         GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK         GENMASK(11, 8)
+#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
@@ -241,7 +242,7 @@ static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
        regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-                          BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
+                          SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
                           value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
 
        return 0;
index e978a63d3222c04cd72788547b421deafdd38517..036e667596eb17c383e46cdc331961b9ed3c2ab2 100644 (file)
@@ -4,10 +4,7 @@
 
 #include <stdio.h>
 
-/* controllable printf */
-extern int pr_output;
-#define printk(fmt, ...)       \
-       (pr_output ? printf(fmt, ##__VA_ARGS__) : 0)
+#define printk(fmt, ...) printf(fmt, ##__VA_ARGS__)
 
 #define pr_err printk
 #define pr_warn        printk
index e18eeb070562bfd44304e99b2256556f40f723b4..a9b97814d1a937b139893076fbdcb47b9bd05d50 100644 (file)
@@ -14,8 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/bootconfig.h>
 
-int pr_output = 1;
-
 static int xbc_show_array(struct xbc_node *node)
 {
        const char *val;
@@ -131,15 +129,26 @@ int load_xbc_from_initrd(int fd, char **buf)
        struct stat stat;
        int ret;
        u32 size = 0, csum = 0, rcsum;
+       char magic[BOOTCONFIG_MAGIC_LEN];
 
        ret = fstat(fd, &stat);
        if (ret < 0)
                return -errno;
 
-       if (stat.st_size < 8)
+       if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
+               return 0;
+
+       if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
+               pr_err("Failed to lseek: %d\n", -errno);
+               return -errno;
+       }
+       if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
+               return -errno;
+       /* Check the bootconfig magic bytes */
+       if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
                return 0;
 
-       if (lseek(fd, -8, SEEK_END) < 0) {
+       if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -150,11 +159,14 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (read(fd, &csum, sizeof(u32)) < 0)
                return -errno;
 
-       /* Wrong size, maybe no boot config here */
-       if (stat.st_size < size + 8)
-               return 0;
+       /* Wrong size error  */
+       if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
+               pr_err("bootconfig size is too big\n");
+               return -E2BIG;
+       }
 
-       if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) {
+       if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
+                 SEEK_SET) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -163,17 +175,17 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (ret < 0)
                return ret;
 
-       /* Wrong Checksum, maybe no boot config here */
+       /* Wrong Checksum */
        rcsum = checksum((unsigned char *)*buf, size);
        if (csum != rcsum) {
                pr_err("checksum error: %d != %d\n", csum, rcsum);
-               return 0;
+               return -EINVAL;
        }
 
        ret = xbc_init(*buf);
-       /* Wrong data, maybe no boot config here */
+       /* Wrong data */
        if (ret < 0)
-               return 0;
+               return ret;
 
        return size;
 }
@@ -213,20 +225,15 @@ int delete_xbc(const char *path)
                return -errno;
        }
 
-       /*
-        * Suppress error messages in xbc_init() because it can be just a
-        * data which concidentally matches the size and checksum footer.
-        */
-       pr_output = 0;
        size = load_xbc_from_initrd(fd, &buf);
-       pr_output = 1;
        if (size < 0) {
                ret = size;
                pr_err("Failed to load a boot config from initrd: %d\n", ret);
        } else if (size > 0) {
                ret = fstat(fd, &stat);
                if (!ret)
-                       ret = ftruncate(fd, stat.st_size - size - 8);
+                       ret = ftruncate(fd, stat.st_size
+                                       - size - 8 - BOOTCONFIG_MAGIC_LEN);
                if (ret)
                        ret = -errno;
        } /* Ignore if there is no boot config in initrd */
@@ -295,6 +302,12 @@ int apply_xbc(const char *path, const char *xbc_path)
                pr_err("Failed to apply a boot config: %d\n", ret);
                return ret;
        }
+       /* Write a magic word of the bootconfig */
+       ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
+       if (ret < 0) {
+               pr_err("Failed to apply a boot config magic: %d\n", ret);
+               return ret;
+       }
        close(fd);
        free(data);
 
diff --git a/tools/bootconfig/samples/bad-mixed-kv1.bconf b/tools/bootconfig/samples/bad-mixed-kv1.bconf
new file mode 100644 (file)
index 0000000..1761547
--- /dev/null
@@ -0,0 +1,3 @@
+# value -> subkey pattern
+key = value
+key.subkey = another-value
diff --git a/tools/bootconfig/samples/bad-mixed-kv2.bconf b/tools/bootconfig/samples/bad-mixed-kv2.bconf
new file mode 100644 (file)
index 0000000..6b32e0c
--- /dev/null
@@ -0,0 +1,3 @@
+# subkey -> value pattern
+key.subkey = value
+key = another-value
diff --git a/tools/bootconfig/samples/bad-samekey.bconf b/tools/bootconfig/samples/bad-samekey.bconf
new file mode 100644 (file)
index 0000000..e8d983a
--- /dev/null
@@ -0,0 +1,6 @@
+# Same key value is not allowed
+key {
+       foo = value
+       bar = value2
+}
+key.foo = value
index 1de06de328e20ccf61fd4d832ad94c0c46e99008..1411f4c3454fbdb55cb1e290f71fc9849fa931ce 100755 (executable)
@@ -9,7 +9,7 @@ TEMPCONF=`mktemp temp-XXXX.bconf`
 NG=0
 
 cleanup() {
-  rm -f $INITRD $TEMPCONF
+  rm -f $INITRD $TEMPCONF $OUTFILE
   exit $NG
 }
 
@@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
 new_size=$(stat -c %s $INITRD)
 
 echo "File size check"
-xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9)
+xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
 
 echo "Apply command repeat test"
 xpass $BOOTCONF -a $TEMPCONF $INITRD
@@ -71,7 +71,6 @@ printf " \0\0\0 \0\0\0" >> $INITRD
 $BOOTCONF -a $TEMPCONF $INITRD > $OUTFILE 2>&1
 xfail grep -i "failed" $OUTFILE
 xfail grep -i "error" $OUTFILE
-rm $OUTFILE
 
 echo "Max node number check"
 
@@ -96,6 +95,19 @@ truncate -s 32764 $TEMPCONF
 echo "\"" >> $TEMPCONF # add 2 bytes + terminal ('\"\n\0')
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 
+echo "Adding same-key values"
+cat > $TEMPCONF << EOF
+key = bar, baz
+key += qux
+EOF
+echo > $INITRD
+
+xpass $BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $OUTFILE
+xpass grep -q "bar" $OUTFILE
+xpass grep -q "baz" $OUTFILE
+xpass grep -q "qux" $OUTFILE
+
 echo "=== expected failure cases ==="
 for i in samples/bad-* ; do
   xfail $BOOTCONF -a $i $INITRD
index f1d74a2bd23493635afcbd6a7336c2fd2806f471..22f235260a3a352cf4223249fc1d26f2fce62f34 100644 (file)
@@ -1045,9 +1045,9 @@ union bpf_attr {
  *             supports redirection to the egress interface, and accepts no
  *             flag at all.
  *
- *             The same effect can be attained with the more generic
- *             **bpf_redirect_map**\ (), which requires specific maps to be
- *             used but offers better performance.
+ *             The same effect can also be attained with the more generic
+ *             **bpf_redirect_map**\ (), which uses a BPF map to store the
+ *             redirect target instead of providing it directly to the helper.
  *     Return
  *             For XDP, the helper returns **XDP_REDIRECT** on success or
  *             **XDP_ABORTED** on error. For other program types, the values
@@ -1611,13 +1611,11 @@ union bpf_attr {
  *             the caller. Any higher bits in the *flags* argument must be
  *             unset.
  *
- *             When used to redirect packets to net devices, this helper
- *             provides a high performance increase over **bpf_redirect**\ ().
- *             This is due to various implementation details of the underlying
- *             mechanisms, one of which is the fact that **bpf_redirect_map**\
- *             () tries to send packet as a "bulk" to the device.
+ *             See also bpf_redirect(), which only supports redirecting to an
+ *             ifindex, but doesn't require a map to do so.
  *     Return
- *             **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
+ *             **XDP_REDIRECT** on success, or the value of the two lower bits
+ *             of the **flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 4cf93110c2596b91c408dd97ef4405c3ad262465..e83fc8e868f45db6c023fb6bfc5d63cf74daa130 100755 (executable)
@@ -25,7 +25,7 @@ import sys
 import locale
 import os
 import time
-import optparse
+import argparse
 import ctypes
 import fcntl
 import resource
@@ -33,6 +33,8 @@ import struct
 import re
 import subprocess
 from collections import defaultdict, namedtuple
+from functools import reduce
+from datetime import datetime
 
 VMX_EXIT_REASONS = {
     'EXCEPTION_NMI':        0,
@@ -873,7 +875,7 @@ class Stats(object):
 
         if options.debugfs:
             providers.append(DebugfsProvider(options.pid, options.fields,
-                                             options.dbgfs_include_past))
+                                             options.debugfs_include_past))
         if options.tracepoints or not providers:
             providers.append(TracepointProvider(options.pid, options.fields))
 
@@ -974,15 +976,17 @@ DELAY_DEFAULT = 3.0
 MAX_GUEST_NAME_LEN = 48
 MAX_REGEX_LEN = 44
 SORT_DEFAULT = 0
+MIN_DELAY = 0.1
+MAX_DELAY = 25.5
 
 
 class Tui(object):
     """Instruments curses to draw a nice text ui."""
-    def __init__(self, stats):
+    def __init__(self, stats, opts):
         self.stats = stats
         self.screen = None
         self._delay_initial = 0.25
-        self._delay_regular = DELAY_DEFAULT
+        self._delay_regular = opts.set_delay
         self._sorting = SORT_DEFAULT
         self._display_guests = 0
 
@@ -1183,7 +1187,7 @@ class Tui(object):
 
         if not self._is_running_guest(self.stats.pid_filter):
             if self._gname:
-                try: # ...to identify the guest by name in case it's back
+                try:  # ...to identify the guest by name in case it's back
                     pids = self.get_pid_from_gname(self._gname)
                     if len(pids) == 1:
                         self._refresh_header(pids[0])
@@ -1282,7 +1286,8 @@ class Tui(object):
                '   p     filter by guest name/PID',
                '   q     quit',
                '   r     reset stats',
-               '   s     set update interval',
+               '   s     set delay between refreshs (value range: '
+               '%s-%s secs)' % (MIN_DELAY, MAX_DELAY),
                '   x     toggle reporting of stats for individual child trace'
                ' events',
                'Any other key refreshes statistics immediately')
@@ -1336,8 +1341,8 @@ class Tui(object):
         msg = ''
         while True:
             self.screen.erase()
-            self.screen.addstr(0, 0, 'Set update interval (defaults to %.1fs).' %
-                               DELAY_DEFAULT, curses.A_BOLD)
+            self.screen.addstr(0, 0, 'Set update interval (defaults to %.1fs).'
+                               DELAY_DEFAULT, curses.A_BOLD)
             self.screen.addstr(4, 0, msg)
             self.screen.addstr(2, 0, 'Change delay from %.1fs to ' %
                                self._delay_regular)
@@ -1348,11 +1353,9 @@ class Tui(object):
             try:
                 if len(val) > 0:
                     delay = float(val)
-                    if delay < 0.1:
-                        msg = '"' + str(val) + '": Value must be >=0.1'
-                        continue
-                    if delay > 25.5:
-                        msg = '"' + str(val) + '": Value must be <=25.5'
+                    err = is_delay_valid(delay)
+                    if err is not None:
+                        msg = err
                         continue
                 else:
                     delay = DELAY_DEFAULT
@@ -1488,33 +1491,64 @@ def batch(stats):
         pass
 
 
-def log(stats):
-    """Prints statistics as reiterating key block, multiple value blocks."""
-    keys = sorted(stats.get().keys())
-
-    def banner():
+class StdFormat(object):
+    def __init__(self, keys):
+        self._banner = ''
         for key in keys:
-            print(key.split(' ')[0], end=' ')
-        print()
+            self._banner += key.split(' ')[0] + ' '
 
-    def statline():
-        s = stats.get()
+    def get_banner(self):
+        return self._banner
+
+    @staticmethod
+    def get_statline(keys, s):
+        res = ''
         for key in keys:
-            print(' %9d' % s[key].delta, end=' ')
-        print()
+            res += ' %9d' % s[key].delta
+        return res
+
+
+class CSVFormat(object):
+    def __init__(self, keys):
+        self._banner = 'timestamp'
+        self._banner += reduce(lambda res, key: "{},{!s}".format(res,
+                               key.split(' ')[0]), keys, '')
+
+    def get_banner(self):
+        return self._banner
+
+    @staticmethod
+    def get_statline(keys, s):
+        return reduce(lambda res, key: "{},{!s}".format(res, s[key].delta),
+                      keys, '')
+
+
+def log(stats, opts, frmt, keys):
+    """Prints statistics as reiterating key block, multiple value blocks."""
     line = 0
     banner_repeat = 20
     while True:
         try:
-            time.sleep(1)
+            time.sleep(opts.set_delay)
             if line % banner_repeat == 0:
-                banner()
-            statline()
+                print(frmt.get_banner())
+            print(datetime.now().strftime("%Y-%m-%d %H:%M:%S") +
+                  frmt.get_statline(keys, stats.get()))
             line += 1
         except KeyboardInterrupt:
             break
 
 
+def is_delay_valid(delay):
+    """Verify delay is in valid value range."""
+    msg = None
+    if delay < MIN_DELAY:
+        msg = '"' + str(delay) + '": Delay must be >=%s' % MIN_DELAY
+    if delay > MAX_DELAY:
+        msg = '"' + str(delay) + '": Delay must be <=%s' % MAX_DELAY
+    return msg
+
+
 def get_options():
     """Returns processed program arguments."""
     description_text = """
@@ -1545,89 +1579,85 @@ Interactive Commands:
    p     filter by PID
    q     quit
    r     reset stats
-   s     set update interval
+   s     set update interval (value range: 0.1-25.5 secs)
    x     toggle reporting of stats for individual child trace events
 Press any other key to refresh statistics immediately.
 """ % (PATH_DEBUGFS_KVM, PATH_DEBUGFS_TRACING)
 
-    class PlainHelpFormatter(optparse.IndentedHelpFormatter):
-        def format_description(self, description):
-            if description:
-                return description + "\n"
-            else:
-                return ""
-
-    def cb_guest_to_pid(option, opt, val, parser):
-        try:
-            pids = Tui.get_pid_from_gname(val)
-        except:
-            sys.exit('Error while searching for guest "{}". Use "-p" to '
-                     'specify a pid instead?'.format(val))
-        if len(pids) == 0:
-            sys.exit('Error: No guest by the name "{}" found'.format(val))
-        if len(pids) > 1:
-            sys.exit('Error: Multiple processes found (pids: {}). Use "-p" '
-                     'to specify the desired pid'.format(" ".join(pids)))
-        parser.values.pid = pids[0]
-
-    optparser = optparse.OptionParser(description=description_text,
-                                      formatter=PlainHelpFormatter())
-    optparser.add_option('-1', '--once', '--batch',
-                         action='store_true',
-                         default=False,
-                         dest='once',
-                         help='run in batch mode for one second',
-                         )
-    optparser.add_option('-i', '--debugfs-include-past',
-                         action='store_true',
-                         default=False,
-                         dest='dbgfs_include_past',
-                         help='include all available data on past events for '
-                              'debugfs',
-                         )
-    optparser.add_option('-l', '--log',
-                         action='store_true',
-                         default=False,
-                         dest='log',
-                         help='run in logging mode (like vmstat)',
-                         )
-    optparser.add_option('-t', '--tracepoints',
-                         action='store_true',
-                         default=False,
-                         dest='tracepoints',
-                         help='retrieve statistics from tracepoints',
-                         )
-    optparser.add_option('-d', '--debugfs',
-                         action='store_true',
-                         default=False,
-                         dest='debugfs',
-                         help='retrieve statistics from debugfs',
-                         )
-    optparser.add_option('-f', '--fields',
-                         action='store',
-                         default='',
-                         dest='fields',
-                         help='''fields to display (regex)
-                                 "-f help" for a list of available events''',
-                         )
-    optparser.add_option('-p', '--pid',
-                         action='store',
-                         default=0,
-                         type='int',
-                         dest='pid',
-                         help='restrict statistics to pid',
-                         )
-    optparser.add_option('-g', '--guest',
-                         action='callback',
-                         type='string',
-                         dest='pid',
-                         metavar='GUEST',
-                         help='restrict statistics to guest by name',
-                         callback=cb_guest_to_pid,
-                         )
-    options, unkn = optparser.parse_args(sys.argv)
-    if len(unkn) != 1:
-        sys.exit('Error: Extra argument(s): ' + ' '.join(unkn[1:]))
+    class Guest_to_pid(argparse.Action):
+        def __call__(self, parser, namespace, values, option_string=None):
+            try:
+                pids = Tui.get_pid_from_gname(values)
+            except:
+                sys.exit('Error while searching for guest "{}". Use "-p" to '
+                         'specify a pid instead?'.format(values))
+            if len(pids) == 0:
+                sys.exit('Error: No guest by the name "{}" found'
+                         .format(values))
+            if len(pids) > 1:
+                sys.exit('Error: Multiple processes found (pids: {}). Use "-p"'
+                         ' to specify the desired pid'.format(" ".join(pids)))
+            namespace.pid = pids[0]
+
+    argparser = argparse.ArgumentParser(description=description_text,
+                                        formatter_class=argparse
+                                        .RawTextHelpFormatter)
+    argparser.add_argument('-1', '--once', '--batch',
+                           action='store_true',
+                           default=False,
+                           help='run in batch mode for one second',
+                           )
+    argparser.add_argument('-c', '--csv',
+                           action='store_true',
+                           default=False,
+                           help='log in csv format - requires option -l/--log',
+                           )
+    argparser.add_argument('-d', '--debugfs',
+                           action='store_true',
+                           default=False,
+                           help='retrieve statistics from debugfs',
+                           )
+    argparser.add_argument('-f', '--fields',
+                           default='',
+                           help='''fields to display (regex)
+"-f help" for a list of available events''',
+                           )
+    argparser.add_argument('-g', '--guest',
+                           type=str,
+                           help='restrict statistics to guest by name',
+                           action=Guest_to_pid,
+                           )
+    argparser.add_argument('-i', '--debugfs-include-past',
+                           action='store_true',
+                           default=False,
+                           help='include all available data on past events for'
+                                ' debugfs',
+                           )
+    argparser.add_argument('-l', '--log',
+                           action='store_true',
+                           default=False,
+                           help='run in logging mode (like vmstat)',
+                           )
+    argparser.add_argument('-p', '--pid',
+                           type=int,
+                           default=0,
+                           help='restrict statistics to pid',
+                           )
+    argparser.add_argument('-s', '--set-delay',
+                           type=float,
+                           default=DELAY_DEFAULT,
+                           metavar='DELAY',
+                           help='set delay between refreshs (value range: '
+                                '%s-%s secs)' % (MIN_DELAY, MAX_DELAY),
+                           )
+    argparser.add_argument('-t', '--tracepoints',
+                           action='store_true',
+                           default=False,
+                           help='retrieve statistics from tracepoints',
+                           )
+    options = argparser.parse_args()
+    if options.csv and not options.log:
+        sys.exit('Error: Option -c/--csv requires -l/--log')
     try:
         # verify that we were passed a valid regex up front
         re.compile(options.fields)
@@ -1693,6 +1723,10 @@ def main():
         sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n')
         sys.exit('Specified pid does not exist.')
 
+    err = is_delay_valid(options.set_delay)
+    if err is not None:
+        sys.exit('Error: ' + err)
+
     stats = Stats(options)
 
     if options.fields == 'help':
@@ -1704,12 +1738,18 @@ def main():
         sys.exit(0)
 
     if options.log:
-        log(stats)
+        keys = sorted(stats.get().keys())
+        if options.csv:
+            frmt = CSVFormat(keys)
+        else:
+            frmt = StdFormat(keys)
+        log(stats, options, frmt, keys)
     elif not options.once:
-        with Tui(stats) as tui:
+        with Tui(stats, options) as tui:
             tui.show_stats()
     else:
         batch(stats)
 
+
 if __name__ == "__main__":
     main()
index c057ba52364e0fffe22a50cc1e1f4fd2c4ec16f9..a97ded2aedadf23d9c2a45c91b8ea50be84a27e3 100644 (file)
@@ -49,7 +49,7 @@ INTERACTIVE COMMANDS
 
 *r*::  reset stats
 
-*s*::   set update interval
+*s*::   set delay between refreshs
 
 *x*::  toggle reporting of stats for child trace events
  ::     *Note*: The stats for the parents summarize the respective child trace
@@ -64,37 +64,45 @@ OPTIONS
 --batch::
        run in batch mode for one second
 
--l::
---log::
-       run in logging mode (like vmstat)
-
--t::
---tracepoints::
-       retrieve statistics from tracepoints
+-c::
+--csv=<file>::
+        log in csv format - requires option -l/--log
 
 -d::
 --debugfs::
        retrieve statistics from debugfs
 
+-f<fields>::
+--fields=<fields>::
+        fields to display (regex), "-f help" for a list of available events
+
+-g<guest>::
+--guest=<guest_name>::
+        limit statistics to one virtual machine (guest name)
+
+-h::
+--help::
+        show help message
+
 -i::
 --debugfs-include-past::
        include all available data on past events for debugfs
 
+-l::
+--log::
+        run in logging mode (like vmstat)
+
 -p<pid>::
 --pid=<pid>::
        limit statistics to one virtual machine (pid)
 
--g<guest>::
---guest=<guest_name>::
-       limit statistics to one virtual machine (guest name)
+-s::
+--set-delay::
+        set delay between refreshs (value range: 0.1-25.5 secs)
 
--f<fields>::
---fields=<fields>::
-       fields to display (regex), "-f help" for a list of available events
-
--h::
---help::
-       show help message
+-t::
+--tracepoints::
+        retrieve statistics from tracepoints
 
 SEE ALSO
 --------
index 514b1a524abbc0ff49bfe25fa2244eb50b860e1c..7469c7dcc15e71fb82e0c8d0a1426cce7b7e2127 100644 (file)
@@ -24,6 +24,7 @@
 #include <endian.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <ctype.h>
 #include <asm/unistd.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -1283,7 +1284,7 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
 static char *internal_map_name(struct bpf_object *obj,
                               enum libbpf_map_type type)
 {
-       char map_name[BPF_OBJ_NAME_LEN];
+       char map_name[BPF_OBJ_NAME_LEN], *p;
        const char *sfx = libbpf_type_to_btf_name[type];
        int sfx_len = max((size_t)7, strlen(sfx));
        int pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1,
@@ -1292,6 +1293,11 @@ static char *internal_map_name(struct bpf_object *obj,
        snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name,
                 sfx_len, libbpf_type_to_btf_name[type]);
 
+       /* sanitise map name to characters allowed by kernel */
+       for (p = map_name; *p && p < map_name + sizeof(map_name); p++)
+               if (!isalnum(*p) && *p != '_' && *p != '.')
+                       *p = '_';
+
        return strdup(map_name);
 }
 
index e59eb9e7f9236b5dc872b270b21b072b4886b6ef..180ad1e1b04f91a4f5e7a956436d872a54d5384c 100755 (executable)
@@ -24,6 +24,8 @@ KunitResult = namedtuple('KunitResult', ['status','result'])
 
 KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
 
+KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0]
+
 class KunitStatus(Enum):
        SUCCESS = auto()
        CONFIG_FAILURE = auto()
@@ -35,6 +37,13 @@ def create_default_kunitconfig():
                shutil.copyfile('arch/um/configs/kunit_defconfig',
                                kunit_kernel.kunitconfig_path)
 
+def get_kernel_root_path():
+       parts = sys.argv[0] if not __file__ else __file__
+       parts = os.path.realpath(parts).split('tools/testing/kunit')
+       if len(parts) != 2:
+               sys.exit(1)
+       return parts[0]
+
 def run_tests(linux: kunit_kernel.LinuxSourceTree,
              request: KunitRequest) -> KunitResult:
        config_start = time.time()
@@ -114,6 +123,9 @@ def main(argv, linux=None):
        cli_args = parser.parse_args(argv)
 
        if cli_args.subcommand == 'run':
+               if get_kernel_root_path():
+                       os.chdir(get_kernel_root_path())
+
                if cli_args.build_dir:
                        if not os.path.exists(cli_args.build_dir):
                                os.mkdir(cli_args.build_dir)
index cc5d844ecca13bfe57f69f13b9c3180834e90a79..d99ae75ef72fa0b7d8193f890875e33c7fb63dce 100644 (file)
@@ -93,6 +93,20 @@ class LinuxSourceTree(object):
                        return False
                return True
 
+       def validate_config(self, build_dir):
+               kconfig_path = get_kconfig_path(build_dir)
+               validated_kconfig = kunit_config.Kconfig()
+               validated_kconfig.read_from_file(kconfig_path)
+               if not self._kconfig.is_subset_of(validated_kconfig):
+                       invalid = self._kconfig.entries() - validated_kconfig.entries()
+                       message = 'Provided Kconfig is not contained in validated .config. Following fields found in kunitconfig, ' \
+                                         'but not in .config: %s' % (
+                                       ', '.join([str(e) for e in invalid])
+                       )
+                       logging.error(message)
+                       return False
+               return True
+
        def build_config(self, build_dir):
                kconfig_path = get_kconfig_path(build_dir)
                if build_dir and not os.path.exists(build_dir):
@@ -103,12 +117,7 @@ class LinuxSourceTree(object):
                except ConfigError as e:
                        logging.error(e)
                        return False
-               validated_kconfig = kunit_config.Kconfig()
-               validated_kconfig.read_from_file(kconfig_path)
-               if not self._kconfig.is_subset_of(validated_kconfig):
-                       logging.error('Provided Kconfig is not contained in validated .config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def build_reconfig(self, build_dir):
                """Creates a new .config if it is not a subset of the .kunitconfig."""
@@ -133,12 +142,7 @@ class LinuxSourceTree(object):
                except (ConfigError, BuildError) as e:
                        logging.error(e)
                        return False
-               used_kconfig = kunit_config.Kconfig()
-               used_kconfig.read_from_file(get_kconfig_path(build_dir))
-               if not self._kconfig.is_subset_of(used_kconfig):
-                       logging.error('Provided Kconfig is not contained in final config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def run_kernel(self, args=[], timeout=None, build_dir=''):
                args.extend(['mem=256M'])
index 63430e2664c2eaf4942f855bead786b05bf8e785..6ec503912bea1e5547235ecdedd5bde9fc87f85d 100644 (file)
@@ -77,6 +77,12 @@ ifneq ($(SKIP_TARGETS),)
        override TARGETS := $(TMP)
 endif
 
+# User can set FORCE_TARGETS to 1 to require all targets to be successfully
+# built; make will fail if any of the targets cannot be built. If
+# FORCE_TARGETS is not set (the default), make will succeed if at least one
+# of the targets gets built.
+FORCE_TARGETS ?=
+
 # Clear LDFLAGS and MAKEFLAGS if called from main
 # Makefile to avoid test build failures when test
 # Makefile doesn't have explicit build rules.
@@ -151,7 +157,8 @@ all: khdr
        for TARGET in $(TARGETS); do                            \
                BUILD_TARGET=$$BUILD/$$TARGET;                  \
                mkdir $$BUILD_TARGET  -p;                       \
-               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET;      \
+               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET       \
+                               $(if $(FORCE_TARGETS),|| exit); \
                ret=$$((ret * $$?));                            \
        done; exit $$ret;
 
@@ -205,7 +212,8 @@ ifdef INSTALL_PATH
        @ret=1; \
        for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
-               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
+               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install \
+                               $(if $(FORCE_TARGETS),|| exit); \
                ret=$$((ret * $$?));            \
        done; exit $$ret;
 
index 098bcae5f827e949610d702349d386a89a5f6ddd..0800036ed6547d26efc5b89d7fe109f2fcf7c604 100644 (file)
@@ -506,8 +506,10 @@ static void test_syncookie(int type, sa_family_t family)
                .pass_on_failure = 0,
        };
 
-       if (type != SOCK_STREAM)
+       if (type != SOCK_STREAM) {
+               test__skip();
                return;
+       }
 
        /*
         * +1 for TCP-SYN and
@@ -822,8 +824,10 @@ void test_select_reuseport(void)
                goto out;
 
        saved_tcp_fo = read_int_sysctl(TCP_FO_SYSCTL);
+       if (saved_tcp_fo < 0)
+               goto out;
        saved_tcp_syncookie = read_int_sysctl(TCP_SYNCOOKIE_SYSCTL);
-       if (saved_tcp_syncookie < 0 || saved_tcp_syncookie < 0)
+       if (saved_tcp_syncookie < 0)
                goto out;
 
        if (enable_fastopen())
index 07f5b462c2ef5bc11aee156e442b3ac565272d89..aa43e0bd210c3182fe7ebce2f62c5f2def0548de 100644 (file)
@@ -3,6 +3,11 @@
 
 #include "test_progs.h"
 
+#define TCP_REPAIR             19      /* TCP sock is under repair right now */
+
+#define TCP_REPAIR_ON          1
+#define TCP_REPAIR_OFF_NO_WP   -1      /* Turn off without window probes */
+
 static int connected_socket_v4(void)
 {
        struct sockaddr_in addr = {
index cd1f5b3a777461b89b25c9783d54aeadcc4d66d0..d6e106fbce11c7706e061cf23a920b8d0cb03459 100644 (file)
@@ -2,7 +2,7 @@
 all:
 
 TEST_PROGS := ftracetest
-TEST_FILES := test.d
+TEST_FILES := test.d settings
 EXTRA_CLEAN := $(OUTPUT)/logs/*
 
 include ../lib.mk
index 64cfcc75e3c10dc8016f2678f3d06f14863c9f81..f2ee1e889e1350e2c77c0c33b713de96afabc86d 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function pid filters
+# flags: instance
 
 # Make sure that function pid matching filter works.
 # Also test it on an instance directory
@@ -96,13 +97,6 @@ do_test() {
 }
 
 do_test
-
-mkdir instances/foo
-cd instances/foo
-do_test
-cd ../../
-rmdir instances/foo
-
 do_reset
 
 exit 0
index 30996306cabcfe89a47977643e529b122893bb7e..23207829ec752b52a56577a679f5baf3f3f51a46 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 INCLUDES := -I../include -I../../
 CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES)
-LDFLAGS := $(LDFLAGS) -pthread -lrt
+LDLIBS := -lpthread -lrt
 
 HEADERS := \
        ../include/futextest.h \
index d82f7bc060c34bdd40675d051e3faffd152e6136..360cd3ea4cd679a4c8bb7544a6c689ec033c9cad 100644 (file)
@@ -117,8 +117,7 @@ static void *vcpu_worker(void *data)
        struct kvm_vm *vm = args->vm;
        int vcpu_id = args->vcpu_id;
        struct kvm_run *run;
-       struct timespec start;
-       struct timespec end;
+       struct timespec start, end, ts_diff;
 
        vcpu_args_set(vm, vcpu_id, 1, vcpu_id);
        run = vcpu_state(vm, vcpu_id);
@@ -135,9 +134,9 @@ static void *vcpu_worker(void *data)
        }
 
        clock_gettime(CLOCK_MONOTONIC, &end);
-       PER_VCPU_DEBUG("vCPU %d execution time: %lld.%.9lds\n", vcpu_id,
-                      (long long)(timespec_diff(start, end).tv_sec),
-                      timespec_diff(start, end).tv_nsec);
+       ts_diff = timespec_sub(end, start);
+       PER_VCPU_DEBUG("vCPU %d execution time: %ld.%.9lds\n", vcpu_id,
+                      ts_diff.tv_sec, ts_diff.tv_nsec);
 
        return NULL;
 }
@@ -201,8 +200,8 @@ static int handle_uffd_page_request(int uffd, uint64_t addr)
 
        clock_gettime(CLOCK_MONOTONIC, &end);
 
-       PER_PAGE_DEBUG("UFFDIO_COPY %d \t%lld ns\n", tid,
-                      (long long)timespec_to_ns(timespec_diff(start, end)));
+       PER_PAGE_DEBUG("UFFDIO_COPY %d \t%ld ns\n", tid,
+                      timespec_to_ns(timespec_sub(end, start)));
        PER_PAGE_DEBUG("Paged in %ld bytes at 0x%lx from thread %d\n",
                       host_page_size, addr, tid);
 
@@ -224,8 +223,7 @@ static void *uffd_handler_thread_fn(void *arg)
        int pipefd = uffd_args->pipefd;
        useconds_t delay = uffd_args->delay;
        int64_t pages = 0;
-       struct timespec start;
-       struct timespec end;
+       struct timespec start, end, ts_diff;
 
        clock_gettime(CLOCK_MONOTONIC, &start);
        while (!quit_uffd_thread) {
@@ -295,11 +293,10 @@ static void *uffd_handler_thread_fn(void *arg)
        }
 
        clock_gettime(CLOCK_MONOTONIC, &end);
-       PER_VCPU_DEBUG("userfaulted %ld pages over %lld.%.9lds. (%f/sec)\n",
-                      pages, (long long)(timespec_diff(start, end).tv_sec),
-                      timespec_diff(start, end).tv_nsec, pages /
-                      ((double)timespec_diff(start, end).tv_sec +
-                       (double)timespec_diff(start, end).tv_nsec / 100000000.0));
+       ts_diff = timespec_sub(end, start);
+       PER_VCPU_DEBUG("userfaulted %ld pages over %ld.%.9lds. (%f/sec)\n",
+                      pages, ts_diff.tv_sec, ts_diff.tv_nsec,
+                      pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0));
 
        return NULL;
 }
@@ -360,13 +357,12 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
        pthread_t *vcpu_threads;
        pthread_t *uffd_handler_threads = NULL;
        struct uffd_handler_args *uffd_args = NULL;
+       struct timespec start, end, ts_diff;
        int *pipefds = NULL;
        struct kvm_vm *vm;
        uint64_t guest_num_pages;
        int vcpu_id;
        int r;
-       struct timespec start;
-       struct timespec end;
 
        vm = create_vm(mode, vcpus, vcpu_memory_bytes);
 
@@ -514,12 +510,11 @@ static void run_test(enum vm_guest_mode mode, bool use_uffd,
                }
        }
 
-       pr_info("Total guest execution time: %lld.%.9lds\n",
-               (long long)(timespec_diff(start, end).tv_sec),
-               timespec_diff(start, end).tv_nsec);
+       ts_diff = timespec_sub(end, start);
+       pr_info("Total guest execution time: %ld.%.9lds\n",
+               ts_diff.tv_sec, ts_diff.tv_nsec);
        pr_info("Overall demand paging rate: %f pgs/sec\n",
-               guest_num_pages / ((double)timespec_diff(start, end).tv_sec +
-               (double)timespec_diff(start, end).tv_nsec / 100000000.0));
+               guest_num_pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / 100000000.0));
 
        ucall_uninit(vm);
        kvm_vm_free(vm);
index f588ad1403f185eebffeae21d9335d87d8a69b15..5eb01bf51b86fc356cb220aa458096da1b744096 100644 (file)
@@ -61,7 +61,8 @@ void test_assert(bool exp, const char *exp_str,
 size_t parse_size(const char *size);
 
 int64_t timespec_to_ns(struct timespec ts);
-struct timespec timespec_diff(struct timespec start, struct timespec end);
 struct timespec timespec_add_ns(struct timespec ts, int64_t ns);
+struct timespec timespec_add(struct timespec ts1, struct timespec ts2);
+struct timespec timespec_sub(struct timespec ts1, struct timespec ts2);
 
 #endif /* SELFTEST_KVM_TEST_UTIL_H */
index 0cf98ad59e325de305d50e042a4a6fd7ce32d444..8a3523d4434fb3fa5887239bc9e70ee7c9992ff4 100644 (file)
@@ -764,7 +764,7 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags)
  * Input Args:
  *   vm - Virtual Machine
  *   slot - Slot of the memory region to move
- *   flags - Starting guest physical address
+ *   new_gpa - Starting guest physical address
  *
  * Output Args: None
  *
@@ -784,7 +784,7 @@ void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa)
        ret = ioctl(vm->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
 
        TEST_ASSERT(!ret, "KVM_SET_USER_MEMORY_REGION failed\n"
-                   "ret: %i errno: %i slot: %u flags: 0x%lx",
+                   "ret: %i errno: %i slot: %u new_gpa: 0x%lx",
                    ret, errno, slot, new_gpa);
 }
 
index ee12c4b9ae050d44a05edd8e10f19c046f988688..689e97c27ee24a244164e51d7edf79868208e472 100644 (file)
@@ -56,36 +56,31 @@ int64_t timespec_to_ns(struct timespec ts)
        return (int64_t)ts.tv_nsec + 1000000000LL * (int64_t)ts.tv_sec;
 }
 
-struct timespec timespec_diff(struct timespec start, struct timespec end)
-{
-       struct timespec temp;
-
-       if ((end.tv_nsec - start.tv_nsec) < 0) {
-               temp.tv_sec = end.tv_sec - start.tv_sec - 1;
-               temp.tv_nsec = 1000000000LL + end.tv_nsec - start.tv_nsec;
-       } else {
-               temp.tv_sec = end.tv_sec - start.tv_sec;
-               temp.tv_nsec = end.tv_nsec - start.tv_nsec;
-       }
-
-       return temp;
-}
-
 struct timespec timespec_add_ns(struct timespec ts, int64_t ns)
 {
        struct timespec res;
 
-       res.tv_sec = ts.tv_sec;
        res.tv_nsec = ts.tv_nsec + ns;
-
-       if (res.tv_nsec > 1000000000UL) {
-               res.tv_sec += 1;
-               res.tv_nsec -= 1000000000UL;
-       }
+       res.tv_sec = ts.tv_sec + res.tv_nsec / 1000000000LL;
+       res.tv_nsec %= 1000000000LL;
 
        return res;
 }
 
+struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
+{
+       int64_t ns1 = timespec_to_ns(ts1);
+       int64_t ns2 = timespec_to_ns(ts2);
+       return timespec_add_ns((struct timespec){0}, ns1 + ns2);
+}
+
+struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
+{
+       int64_t ns1 = timespec_to_ns(ts1);
+       int64_t ns2 = timespec_to_ns(ts2);
+       return timespec_add_ns((struct timespec){0}, ns1 - ns2);
+}
+
 void print_skip(const char *fmt, ...)
 {
        va_list ap;
index f976ac5e896adf8bd596481b23508ede5a1e6238..fcc840088c919a29c06f074e7515336982aa53c3 100644 (file)
@@ -242,7 +242,7 @@ static void *do_steal_time(void *arg)
 
        while (1) {
                clock_gettime(CLOCK_MONOTONIC, &ts);
-               if (ts.tv_sec > stop.tv_sec || ts.tv_nsec >= stop.tv_nsec)
+               if (timespec_to_ns(timespec_sub(ts, stop)) >= 0)
                        break;
        }
 
index 1c8a1963d03f8acf349ae209e5db03ab79e2614e..3ed0134a764d494f6b451fddfa45fee58f11611a 100644 (file)
@@ -83,17 +83,20 @@ else
        $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
 endif
 
+define INSTALL_SINGLE_RULE
+       $(if $(INSTALL_LIST),@mkdir -p $(INSTALL_PATH))
+       $(if $(INSTALL_LIST),@echo rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/)
+       $(if $(INSTALL_LIST),@rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/)
+endef
+
 define INSTALL_RULE
-       @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then                                        \
-               mkdir -p ${INSTALL_PATH};                                                                               \
-               echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/";    \
-               rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/;           \
-       fi
-       @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then                                        \
-               mkdir -p ${INSTALL_PATH};                                                                               \
-               echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/";   \
-               rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/;          \
-       fi
+       $(eval INSTALL_LIST = $(TEST_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_FILES)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_CUSTOM_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_FILES)) $(INSTALL_SINGLE_RULE)
 endef
 
 install: all
index 3876d8d62494443297b0da55cb88bbe5f2da5210..1acc9e1fa3fbca78db5fca858f01c042a2fe62ff 100644 (file)
@@ -8,4 +8,6 @@ TEST_PROGS := \
        test-state.sh \
        test-ftrace.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
index b5694196430ae2334b83cdeb465bf3e7d36080f5..287ae916ec0b4b8e22b886ec65ac0c21fdedc72a 100644 (file)
@@ -27,5 +27,5 @@ KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
 $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
-$(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread
-$(OUTPUT)/tcp_inq: LDFLAGS += -lpthread
+$(OUTPUT)/tcp_mmap: LDLIBS += -lpthread
+$(OUTPUT)/tcp_inq: LDLIBS += -lpthread
index 6dd4031038008bef871a66ea1e3ebfdf7d8b964f..60273f1bc7d9c0cfe8324d8bd4b256cc88ad2fff 100755 (executable)
@@ -910,6 +910,12 @@ ipv6_rt_replace_mpath()
        check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
        log_test $? 0 "Multipath with single path via multipath attribute"
 
+       # multipath with dev-only
+       add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
+       run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
+       check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
+       log_test $? 0 "Multipath with dev-only"
+
        # route replace fails - invalid nexthop 1
        add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
        run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
index e6fd7a18c655ff32e4f4d5ffd033acd866a70c96..0266443601bc0bb90504132a1c1b57aced95089b 100755 (executable)
@@ -63,22 +63,23 @@ test_span_gre_mac()
 {
        local tundev=$1; shift
        local direction=$1; shift
-       local prot=$1; shift
        local what=$1; shift
 
-       local swp3mac=$(mac_get $swp3)
-       local h3mac=$(mac_get $h3)
+       case "$direction" in
+       ingress) local src_mac=$(mac_get $h1); local dst_mac=$(mac_get $h2)
+               ;;
+       egress) local src_mac=$(mac_get $h2); local dst_mac=$(mac_get $h1)
+               ;;
+       esac
 
        RET=0
 
        mirror_install $swp1 $direction $tundev "matchall $tcflags"
-       tc filter add dev $h3 ingress pref 77 prot $prot \
-               flower ip_proto 0x2f src_mac $swp3mac dst_mac $h3mac \
-               action pass
+       icmp_capture_install h3-${tundev} "src_mac $src_mac dst_mac $dst_mac"
 
-       mirror_test v$h1 192.0.2.1 192.0.2.2 $h3 77 10
+       mirror_test v$h1 192.0.2.1 192.0.2.2 h3-${tundev} 100 10
 
-       tc filter del dev $h3 ingress pref 77
+       icmp_capture_uninstall h3-${tundev}
        mirror_uninstall $swp1 $direction
 
        log_test "$direction $what: envelope MAC ($tcflags)"
@@ -120,14 +121,14 @@ test_ip6gretap()
 
 test_gretap_mac()
 {
-       test_span_gre_mac gt4 ingress ip "mirror to gretap"
-       test_span_gre_mac gt4 egress ip "mirror to gretap"
+       test_span_gre_mac gt4 ingress "mirror to gretap"
+       test_span_gre_mac gt4 egress "mirror to gretap"
 }
 
 test_ip6gretap_mac()
 {
-       test_span_gre_mac gt6 ingress ipv6 "mirror to ip6gretap"
-       test_span_gre_mac gt6 egress ipv6 "mirror to ip6gretap"
+       test_span_gre_mac gt6 ingress "mirror to ip6gretap"
+       test_span_gre_mac gt6 egress "mirror to ip6gretap"
 }
 
 test_all()
index bb10e33690b25a763d3de18cce207a098baf7351..ce6bea9675c074587ca1ebc51a3402cdcf782ee0 100755 (executable)
@@ -516,9 +516,9 @@ test_tos()
        RET=0
 
        tc filter add dev v1 egress pref 77 prot ip \
-               flower ip_tos 0x40 action pass
-       vxlan_ping_test $h1 192.0.2.3 "-Q 0x40" v1 egress 77 10
-       vxlan_ping_test $h1 192.0.2.3 "-Q 0x30" v1 egress 77 0
+               flower ip_tos 0x14 action pass
+       vxlan_ping_test $h1 192.0.2.3 "-Q 0x14" v1 egress 77 10
+       vxlan_ping_test $h1 192.0.2.3 "-Q 0x18" v1 egress 77 0
        tc filter del dev v1 egress pref 77 prot ip
 
        log_test "VXLAN: envelope TOS inheritance"
index 93de52016ddee400e64ae3ed9eceac8a3b10834b..ba450e62dc5be5e5bccd5f36753ca81c1a74dff7 100644 (file)
@@ -8,6 +8,8 @@ TEST_PROGS := mptcp_connect.sh
 
 TEST_GEN_FILES = mptcp_connect
 
+TEST_FILES := settings
+
 EXTRA_CLEAN := *.pcap
 
 include ../../lib.mk
index aca21dde102abbb05294594d8b3f7483873b87f5..5a4938d6dcf25a3f8137be799091f4f0d16ad7fd 100755 (executable)
 KSELFTEST_SKIP=4
 
 # Available test groups:
+# - reported_issues: check for issues that were reported in the past
 # - correctness: check that packets match given entries, and only those
 # - concurrency: attempt races between insertion, deletion and lookup
 # - timeout: check that packets match entries until they expire
 # - performance: estimate matching rate, compare with rbtree and hash baselines
-TESTS="correctness concurrency timeout"
+TESTS="reported_issues correctness concurrency timeout"
 [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance"
 
 # Set types, defined by TYPE_ variables below
@@ -25,6 +26,9 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
        net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port
        net_port_mac_proto_net"
 
+# Reported bugs, also described by TYPE_ variables below
+BUGS="flush_remove_add"
+
 # List of possible paths to pktgen script from kernel tree for performance tests
 PKTGEN_SCRIPT_PATHS="
        ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
@@ -327,6 +331,12 @@ flood_spec ip daddr . tcp dport . meta l4proto . ip saddr
 perf_duration  0
 "
 
+# Definition of tests for bugs reported in the past:
+# display      display text for test report
+TYPE_flush_remove_add="
+display                Add two elements, flush, re-add
+"
+
 # Set template for all tests, types and rules are filled in depending on test
 set_template='
 flush ruleset
@@ -440,6 +450,8 @@ setup_set() {
 
 # Check that at least one of the needed tools is available
 check_tools() {
+       [ -z "${tools}" ] && return 0
+
        __tools=
        for tool in ${tools}; do
                if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \
@@ -1025,7 +1037,7 @@ format_noconcat() {
 add() {
        if ! nft add element inet filter test "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1045,7 +1057,7 @@ add_perf() {
 add_perf_norange() {
        if ! nft add element netdev perf norange "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1054,7 +1066,7 @@ add_perf_norange() {
 add_perf_noconcat() {
        if ! nft add element netdev perf noconcat "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1063,7 +1075,7 @@ add_perf_noconcat() {
 del() {
        if ! nft delete element inet filter test "${1}"; then
                err "Failed to delete ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1134,7 +1146,7 @@ send_match() {
                err "  $(for f in ${src}; do
                         eval format_\$f "${2}"; printf ' '; done)"
                err "should have matched ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
        nft reset counter inet filter test >/dev/null
@@ -1160,7 +1172,7 @@ send_nomatch() {
                err "  $(for f in ${src}; do
                         eval format_\$f "${2}"; printf ' '; done)"
                err "should not have matched ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1430,6 +1442,23 @@ test_performance() {
        kill "${perf_pid}"
 }
 
+test_bug_flush_remove_add() {
+       set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }'
+       elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }'
+       elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }'
+       for i in `seq 1 100`; do
+               nft add table t ${set_cmd}      || return ${KSELFTEST_SKIP}
+               nft add element t s ${elem1}    2>/dev/null || return 1
+               nft flush set t s               2>/dev/null || return 1
+               nft add element t s ${elem2}    2>/dev/null || return 1
+       done
+       nft flush ruleset
+}
+
+test_reported_issues() {
+       eval test_bug_"${subtest}"
+}
+
 # Run everything in a separate network namespace
 [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
 tmp="$(mktemp)"
@@ -1438,9 +1467,15 @@ trap cleanup EXIT
 # Entry point for test runs
 passed=0
 for name in ${TESTS}; do
-       printf "TEST: %s\n" "${name}"
-       for type in ${TYPES}; do
-               eval desc=\$TYPE_"${type}"
+       printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')"
+       if [ "${name}" = "reported_issues" ]; then
+               SUBTESTS="${BUGS}"
+       else
+               SUBTESTS="${TYPES}"
+       fi
+
+       for subtest in ${SUBTESTS}; do
+               eval desc=\$TYPE_"${subtest}"
                IFS='
 '
                for __line in ${desc}; do
index e9a6557ab16f3b347d98d84d80d008f2488c7bdd..5074681ffdc995dbe3cc903550ef63f3385ba25a 100644 (file)
@@ -46,7 +46,7 @@ int sys_renameat2(int olddirfd, const char *oldpath,
 
 int touchat(int dfd, const char *path)
 {
-       int fd = openat(dfd, path, O_CREAT);
+       int fd = openat(dfd, path, O_CREAT, 0700);
        if (fd >= 0)
                close(fd);
        return fd;
index 7a94b1da8e7bcf2a8413bad5abb3a2cb2de6ed8d..bbafad440893cba427168d42fe3e1620a8dc00e5 100644 (file)
@@ -230,7 +230,7 @@ void test_openat2_opath_tests(void)
                { .name = "[in_root] garbage link to /root",
                  .path = "cheeky/garbageself", .how.resolve = RESOLVE_IN_ROOT,
                  .out.path = "root",           .pass = true },
-               { .name = "[in_root] chainged garbage links to /root",
+               { .name = "[in_root] chained garbage links to /root",
                  .path = "abscheeky/garbageself", .how.resolve = RESOLVE_IN_ROOT,
                  .out.path = "root",           .pass = true },
                { .name = "[in_root] relative path to 'root'",
index d6469535630af888051a9c50e8059a8a2abfac8a..2af9d39a97168c14dc4c008d59017d45146ff5bf 100644 (file)
@@ -4,7 +4,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 CLANG_FLAGS += -no-integrated-as
 endif
 
-CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \
+CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \
          $(CLANG_FLAGS)
 LDLIBS += -lpthread
 
@@ -19,6 +19,8 @@ TEST_GEN_PROGS_EXTENDED = librseq.so
 
 TEST_PROGS = run_param_test.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
 
 $(OUTPUT)/librseq.so: rseq.c rseq.h rseq-*.h
index de9c8566672ae7e4bd7d6d7c321455ff5525b5a2..55198ecc04dbea93c4fb358ebac715527e2755d4 100644 (file)
@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -O3 -Wl,-no-as-needed -Wall
-LDFLAGS += -lrt -lpthread -lm
+LDLIBS += -lrt -lpthread -lm
 
 TEST_GEN_PROGS = rtctest
 
 TEST_GEN_PROGS_EXTENDED = setdate
 
+TEST_FILES := settings
+
 include ../lib.mk
index e9fb30bd8aeb3c0ed846ccdd2aeaf18cb6723592..b4fd9a9346547c71e8331d0ccb165ada9200d15e 100644 (file)
@@ -2,6 +2,6 @@ TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec
 TEST_GEN_PROGS_EXTENDED := gettime_perf
 
 CFLAGS := -Wall -Werror -pthread
-LDFLAGS := -lrt -ldl
+LDLIBS := -lrt -ldl
 
 include ../lib.mk
index 8155c2ea7ccbb6ed1b9685f3c602105eb2c26173..b630c7b5950a960b95a9bb0aeda79e41924ca989 100755 (executable)
@@ -1,8 +1,17 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+self.flags = flags
 
-python -m unittest -v tpm2_tests.SmokeTest
-python -m unittest -v tpm2_tests.AsyncTest
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+
+if [ -f /dev/tpm0 ] ; then
+       python -m unittest -v tpm2_tests.SmokeTest
+       python -m unittest -v tpm2_tests.AsyncTest
+else
+       exit $ksft_skip
+fi
 
 CLEAR_CMD=$(which tpm2_clear)
 if [ -n $CLEAR_CMD ]; then
index a6f5e346635e560db7c7767b22f32f760922600a..180b469c53b47d4e0e2e3d7c6bb2ecc7331065e2 100755 (executable)
@@ -1,4 +1,11 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
-python -m unittest -v tpm2_tests.SpaceTest
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+if [ -f /dev/tpmrm0 ] ; then
+       python -m unittest -v tpm2_tests.SpaceTest
+else
+       exit $ksft_skip
+fi
index a692ea8283177dc8716ae6af24c2b7684471e4c4..f337148431980b821b058a87fb73bd3679d0b316 100755 (executable)
@@ -112,6 +112,17 @@ echo "NOTE: The above hugetlb tests provide minimal coverage.  Use"
 echo "      https://github.com/libhugetlbfs/libhugetlbfs.git for"
 echo "      hugetlb regression testing."
 
+echo "---------------------------"
+echo "running map_fixed_noreplace"
+echo "---------------------------"
+./map_fixed_noreplace
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 echo "-------------------"
 echo "running userfaultfd"
 echo "-------------------"
@@ -186,6 +197,17 @@ else
        echo "[PASS]"
 fi
 
+echo "-------------------------"
+echo "running mlock-random-test"
+echo "-------------------------"
+./mlock-random-test
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 echo "--------------------"
 echo "running mlock2-tests"
 echo "--------------------"
@@ -197,6 +219,17 @@ else
        echo "[PASS]"
 fi
 
+echo "-----------------"
+echo "running thuge-gen"
+echo "-----------------"
+./thuge-gen
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 if [ $VADDR64 -ne 0 ]; then
 echo "-----------------------------"
 echo "running virtual_address_range"
index f10aa3590adc425b4d564eb91adfe4a77250e1bd..28d477683e8abe3c492274f7a71c8b48f9bda00e 100644 (file)
@@ -38,19 +38,17 @@ endef
 define file_download =
 $(DISTFILES_PATH)/$(1):
        mkdir -p $(DISTFILES_PATH)
-       flock -x $$@.lock -c '[ -f $$@ ] && exit 0; wget -O $$@.tmp $(MIRROR)$(1) || wget -O $$@.tmp $(2)$(1) || rm -f $$@.tmp'
-       if echo "$(3)  $$@.tmp" | sha256sum -c -; then mv $$@.tmp $$@; else rm -f $$@.tmp; exit 71; fi
+       flock -x $$@.lock -c '[ -f $$@ ] && exit 0; wget -O $$@.tmp $(MIRROR)$(1) || wget -O $$@.tmp $(2)$(1) || rm -f $$@.tmp; [ -f $$@.tmp ] || exit 1; if echo "$(3)  $$@.tmp" | sha256sum -c -; then mv $$@.tmp $$@; else rm -f $$@.tmp; exit 71; fi'
 endef
 
 $(eval $(call tar_download,MUSL,musl,1.1.24,.tar.gz,https://www.musl-libc.org/releases/,1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3))
-$(eval $(call tar_download,LIBMNL,libmnl,1.0.4,.tar.bz2,https://www.netfilter.org/projects/libmnl/files/,171f89699f286a5854b72b91d06e8f8e3683064c5901fb09d954a9ab6f551f81))
 $(eval $(call tar_download,IPERF,iperf,3.7,.tar.gz,https://downloads.es.net/pub/iperf/,d846040224317caf2f75c843d309a950a7db23f9b44b94688ccbe557d6d1710c))
 $(eval $(call tar_download,BASH,bash,5.0,.tar.gz,https://ftp.gnu.org/gnu/bash/,b4a80f2ac66170b2913efbfb9f2594f1f76c7b1afd11f799e22035d63077fb4d))
 $(eval $(call tar_download,IPROUTE2,iproute2,5.4.0,.tar.xz,https://www.kernel.org/pub/linux/utils/net/iproute2/,fe97aa60a0d4c5ac830be18937e18dc3400ca713a33a89ad896ff1e3d46086ae))
 $(eval $(call tar_download,IPTABLES,iptables,1.8.4,.tar.bz2,https://www.netfilter.org/projects/iptables/files/,993a3a5490a544c2cbf2ef15cf7e7ed21af1845baf228318d5c36ef8827e157c))
 $(eval $(call tar_download,NMAP,nmap,7.80,.tar.bz2,https://nmap.org/dist/,fcfa5a0e42099e12e4bf7a68ebe6fde05553383a682e816a7ec9256ab4773faa))
 $(eval $(call tar_download,IPUTILS,iputils,s20190709,.tar.gz,https://github.com/iputils/iputils/archive/s20190709.tar.gz/#,a15720dd741d7538dd2645f9f516d193636ae4300ff7dbc8bfca757bf166490a))
-$(eval $(call tar_download,WIREGUARD_TOOLS,wireguard-tools,1.0.20191226,.tar.xz,https://git.zx2c4.com/wireguard-tools/snapshot/,aa8af0fdc9872d369d8c890a84dbc2a2466b55795dccd5b47721b2d97644b04f))
+$(eval $(call tar_download,WIREGUARD_TOOLS,wireguard-tools,1.0.20200206,.tar.xz,https://git.zx2c4.com/wireguard-tools/snapshot/,f5207248c6a3c3e3bfc9ab30b91c1897b00802ed861e1f9faaed873366078c64))
 
 KERNEL_BUILD_PATH := $(BUILD_PATH)/kernel$(if $(findstring yes,$(DEBUG_KERNEL)),-debug)
 rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
@@ -295,21 +293,13 @@ $(IPERF_PATH)/src/iperf3: | $(IPERF_PATH)/.installed $(USERSPACE_DEPS)
        $(MAKE) -C $(IPERF_PATH)
        $(STRIP) -s $@
 
-$(LIBMNL_PATH)/.installed: $(LIBMNL_TAR)
-       flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
-       touch $@
-
-$(LIBMNL_PATH)/src/.libs/libmnl.a: | $(LIBMNL_PATH)/.installed $(USERSPACE_DEPS)
-       cd $(LIBMNL_PATH) && ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared
-       $(MAKE) -C $(LIBMNL_PATH)
-       sed -i 's:prefix=.*:prefix=$(LIBMNL_PATH):' $(LIBMNL_PATH)/libmnl.pc
-
 $(WIREGUARD_TOOLS_PATH)/.installed: $(WIREGUARD_TOOLS_TAR)
+       mkdir -p $(BUILD_PATH)
        flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
        touch $@
 
-$(WIREGUARD_TOOLS_PATH)/src/wg: | $(WIREGUARD_TOOLS_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" $(MAKE) -C $(WIREGUARD_TOOLS_PATH)/src LIBMNL_CFLAGS="-I$(LIBMNL_PATH)/include" LIBMNL_LDLIBS="-lmnl" wg
+$(WIREGUARD_TOOLS_PATH)/src/wg: | $(WIREGUARD_TOOLS_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(WIREGUARD_TOOLS_PATH)/src wg
        $(STRIP) -s $@
 
 $(BUILD_PATH)/init: init.c | $(USERSPACE_DEPS)
@@ -340,17 +330,17 @@ $(BASH_PATH)/bash: | $(BASH_PATH)/.installed $(USERSPACE_DEPS)
 $(IPROUTE2_PATH)/.installed: $(IPROUTE2_TAR)
        mkdir -p $(BUILD_PATH)
        flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
-       printf 'CC:=$(CC)\nPKG_CONFIG:=pkg-config\nTC_CONFIG_XT:=n\nTC_CONFIG_ATM:=n\nTC_CONFIG_IPSET:=n\nIP_CONFIG_SETNS:=y\nHAVE_ELF:=n\nHAVE_MNL:=y\nHAVE_BERKELEY_DB:=n\nHAVE_LATEX:=n\nHAVE_PDFLATEX:=n\nCFLAGS+=-DHAVE_SETNS -DHAVE_LIBMNL -I$(LIBMNL_PATH)/include\nLDLIBS+=-lmnl' > $(IPROUTE2_PATH)/config.mk
+       printf 'CC:=$(CC)\nPKG_CONFIG:=pkg-config\nTC_CONFIG_XT:=n\nTC_CONFIG_ATM:=n\nTC_CONFIG_IPSET:=n\nIP_CONFIG_SETNS:=y\nHAVE_ELF:=n\nHAVE_MNL:=n\nHAVE_BERKELEY_DB:=n\nHAVE_LATEX:=n\nHAVE_PDFLATEX:=n\nCFLAGS+=-DHAVE_SETNS\n' > $(IPROUTE2_PATH)/config.mk
        printf 'lib: snapshot\n\t$$(MAKE) -C lib\nip/ip: lib\n\t$$(MAKE) -C ip ip\nmisc/ss: lib\n\t$$(MAKE) -C misc ss\n' >> $(IPROUTE2_PATH)/Makefile
        touch $@
 
-$(IPROUTE2_PATH)/ip/ip: | $(IPROUTE2_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ ip/ip
-       $(STRIP) -s $(IPROUTE2_PATH)/ip/ip
+$(IPROUTE2_PATH)/ip/ip: | $(IPROUTE2_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ ip/ip
+       $(STRIP) -s $@
 
-$(IPROUTE2_PATH)/misc/ss: | $(IPROUTE2_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ misc/ss
-       $(STRIP) -s $(IPROUTE2_PATH)/misc/ss
+$(IPROUTE2_PATH)/misc/ss: | $(IPROUTE2_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ misc/ss
+       $(STRIP) -s $@
 
 $(IPTABLES_PATH)/.installed: $(IPTABLES_TAR)
        mkdir -p $(BUILD_PATH)
@@ -358,8 +348,8 @@ $(IPTABLES_PATH)/.installed: $(IPTABLES_TAR)
        sed -i -e "/nfnetlink=[01]/s:=[01]:=0:" -e "/nfconntrack=[01]/s:=[01]:=0:" $(IPTABLES_PATH)/configure
        touch $@
 
-$(IPTABLES_PATH)/iptables/xtables-legacy-multi: | $(IPTABLES_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       cd $(IPTABLES_PATH) && PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared --disable-nftables --disable-bpf-compiler --disable-nfsynproxy --disable-libipq --with-kernel=$(BUILD_PATH)/include
+$(IPTABLES_PATH)/iptables/xtables-legacy-multi: | $(IPTABLES_PATH)/.installed $(USERSPACE_DEPS)
+       cd $(IPTABLES_PATH) && ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared --disable-nftables --disable-bpf-compiler --disable-nfsynproxy --disable-libipq --disable-connlabel --with-kernel=$(BUILD_PATH)/include
        $(MAKE) -C $(IPTABLES_PATH)
        $(STRIP) -s $@
 
index 0d9438e9de2a99334e83c0759876c3f189fd2a0e..93bd59b46848e202a19cad58ef267e3eabd00740 100644 (file)
@@ -788,7 +788,7 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
                                          vcpu_ptimer(vcpu), TIMER_REG_CTL);
        case KVM_REG_ARM_PTIMER_CNT:
                return kvm_arm_timer_read(vcpu,
-                                         vcpu_vtimer(vcpu), TIMER_REG_CNT);
+                                         vcpu_ptimer(vcpu), TIMER_REG_CNT);
        case KVM_REG_ARM_PTIMER_CVAL:
                return kvm_arm_timer_read(vcpu,
                                          vcpu_ptimer(vcpu), TIMER_REG_CVAL);
index bfdba1caf59d5524fca45df4959c684e1f213b4b..376c6a74166dd1e0f41c0c43f5c081334d583a96 100644 (file)
@@ -625,6 +625,14 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
 
                if (kvm_check_request(KVM_REQ_RECORD_STEAL, vcpu))
                        kvm_update_stolen_time(vcpu);
+
+               if (kvm_check_request(KVM_REQ_RELOAD_GICv4, vcpu)) {
+                       /* The distributor enable bits were changed */
+                       preempt_disable();
+                       vgic_v4_put(vcpu, false);
+                       vgic_v4_load(vcpu);
+                       preempt_enable();
+               }
        }
 }
 
@@ -742,9 +750,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                guest_enter_irqoff();
 
                if (has_vhe()) {
-                       kvm_arm_vhe_guest_enter();
                        ret = kvm_vcpu_run_vhe(vcpu);
-                       kvm_arm_vhe_guest_exit();
                } else {
                        ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
                }
index 204d210d01c29a3282e16ec7c6ed21d25dc315c3..cc94ccc688217c7fa337e01d74ca1378f31699c1 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <kvm/arm_arch_timer.h>
 #include <linux/tracepoint.h>
+#include <asm/kvm_arm.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
index cc12fe9b2df3fbe0f38f5fe080b9678717a2116b..b13a9e3f99ddc13efd1947da8effcd8259c5fef7 100644 (file)
@@ -178,6 +178,8 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
                            struct kvm_vcpu *vcpu)
 {
        char *type;
+       bool pending;
+
        if (irq->intid < VGIC_NR_SGIS)
                type = "SGI";
        else if (irq->intid < VGIC_NR_PRIVATE_IRQS)
@@ -190,6 +192,16 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
        if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
                print_header(s, irq, vcpu);
 
+       pending = irq->pending_latch;
+       if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+               int err;
+
+               err = irq_get_irqchip_state(irq->host_irq,
+                                           IRQCHIP_STATE_PENDING,
+                                           &pending);
+               WARN_ON_ONCE(err);
+       }
+
        seq_printf(s, "       %s %4d "
                      "    %2d "
                      "%d%d%d%d%d%d%d "
@@ -201,7 +213,7 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
                      "\n",
                        type, irq->intid,
                        (irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1,
-                       irq->pending_latch,
+                       pending,
                        irq->line_level,
                        irq->active,
                        irq->enabled,
index ebc218840fc2210908cb0e1e9b8444539bad46f2..e72dcc4542475a74fa1f890532d26cd6945fdad5 100644 (file)
@@ -3,9 +3,11 @@
  * VGICv3 MMIO handling functions
  */
 
+#include <linux/bitfield.h>
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/interrupt.h>
 #include <kvm/iodev.h>
 #include <kvm/arm_vgic.h>
 
@@ -69,6 +71,8 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
                if (vgic->enabled)
                        value |= GICD_CTLR_ENABLE_SS_G1;
                value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
+               if (vgic->nassgireq)
+                       value |= GICD_CTLR_nASSGIreq;
                break;
        case GICD_TYPER:
                value = vgic->nr_spis + VGIC_NR_PRIVATE_IRQS;
@@ -80,6 +84,10 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
                        value |= (INTERRUPT_ID_BITS_SPIS - 1) << 19;
                }
                break;
+       case GICD_TYPER2:
+               if (kvm_vgic_global_state.has_gicv4_1)
+                       value = GICD_TYPER2_nASSGIcap;
+               break;
        case GICD_IIDR:
                value = (PRODUCT_ID_KVM << GICD_IIDR_PRODUCT_ID_SHIFT) |
                        (vgic->implementation_rev << GICD_IIDR_REVISION_SHIFT) |
@@ -97,17 +105,46 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
                                    unsigned long val)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-       bool was_enabled = dist->enabled;
 
        switch (addr & 0x0c) {
-       case GICD_CTLR:
+       case GICD_CTLR: {
+               bool was_enabled, is_hwsgi;
+
+               mutex_lock(&vcpu->kvm->lock);
+
+               was_enabled = dist->enabled;
+               is_hwsgi = dist->nassgireq;
+
                dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
 
-               if (!was_enabled && dist->enabled)
+               /* Not a GICv4.1? No HW SGIs */
+               if (!kvm_vgic_global_state.has_gicv4_1)
+                       val &= ~GICD_CTLR_nASSGIreq;
+
+               /* Dist stays enabled? nASSGIreq is RO */
+               if (was_enabled && dist->enabled) {
+                       val &= ~GICD_CTLR_nASSGIreq;
+                       val |= FIELD_PREP(GICD_CTLR_nASSGIreq, is_hwsgi);
+               }
+
+               /* Switching HW SGIs? */
+               dist->nassgireq = val & GICD_CTLR_nASSGIreq;
+               if (is_hwsgi != dist->nassgireq)
+                       vgic_v4_configure_vsgis(vcpu->kvm);
+
+               if (kvm_vgic_global_state.has_gicv4_1 &&
+                   was_enabled != dist->enabled)
+                       kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_RELOAD_GICv4);
+               else if (!was_enabled && dist->enabled)
                        vgic_kick_vcpus(vcpu->kvm);
+
+               mutex_unlock(&vcpu->kvm->lock);
                break;
+       }
        case GICD_TYPER:
+       case GICD_TYPER2:
        case GICD_IIDR:
+               /* This is at best for documentation purposes... */
                return;
        }
 }
@@ -116,10 +153,22 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
                                           gpa_t addr, unsigned int len,
                                           unsigned long val)
 {
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
        switch (addr & 0x0c) {
+       case GICD_TYPER2:
        case GICD_IIDR:
                if (val != vgic_mmio_read_v3_misc(vcpu, addr, len))
                        return -EINVAL;
+               return 0;
+       case GICD_CTLR:
+               /* Not a GICv4.1? No HW SGIs */
+               if (!kvm_vgic_global_state.has_gicv4_1)
+                       val &= ~GICD_CTLR_nASSGIreq;
+
+               dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
+               dist->nassgireq = val & GICD_CTLR_nASSGIreq;
+               return 0;
        }
 
        vgic_mmio_write_v3_misc(vcpu, addr, len, val);
@@ -257,8 +306,18 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
         */
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+               bool state = irq->pending_latch;
 
-               if (irq->pending_latch)
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       int err;
+
+                       err = irq_get_irqchip_state(irq->host_irq,
+                                                   IRQCHIP_STATE_PENDING,
+                                                   &state);
+                       WARN_ON(err);
+               }
+
+               if (state)
                        value |= (1U << i);
 
                vgic_put_irq(vcpu->kvm, irq);
@@ -942,8 +1001,18 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
                 * generate interrupts of either group.
                 */
                if (!irq->group || allow_group1) {
-                       irq->pending_latch = true;
-                       vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+                       if (!irq->hw) {
+                               irq->pending_latch = true;
+                               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+                       } else {
+                               /* HW SGI? Ask the GIC to inject it */
+                               int err;
+                               err = irq_set_irqchip_state(irq->host_irq,
+                                                           IRQCHIP_STATE_PENDING,
+                                                           true);
+                               WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+                               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       }
                } else {
                        raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
index 97fb2a40e6ba193efc51fa1cf0c05bb0815db648..2199302597fafa32edced522d4df282bb87008dc 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bsearch.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <kvm/iodev.h>
@@ -59,6 +61,11 @@ unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu,
        return value;
 }
 
+static void vgic_update_vsgi(struct vgic_irq *irq)
+{
+       WARN_ON(its_prop_update_vsgi(irq->host_irq, irq->priority, irq->group));
+}
+
 void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
                           unsigned int len, unsigned long val)
 {
@@ -71,7 +78,12 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->group = !!(val & BIT(i));
-               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       vgic_update_vsgi(irq);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+               } else {
+                       vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+               }
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -113,7 +125,21 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
-               if (vgic_irq_is_mapped_level(irq)) {
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       if (!irq->enabled) {
+                               struct irq_data *data;
+
+                               irq->enabled = true;
+                               data = &irq_to_desc(irq->host_irq)->irq_data;
+                               while (irqd_irq_disabled(data))
+                                       enable_irq(irq->host_irq);
+                       }
+
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       vgic_put_irq(vcpu->kvm, irq);
+
+                       continue;
+               } else if (vgic_irq_is_mapped_level(irq)) {
                        bool was_high = irq->line_level;
 
                        /*
@@ -148,6 +174,8 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
+               if (irq->hw && vgic_irq_is_sgi(irq->intid) && irq->enabled)
+                       disable_irq_nosync(irq->host_irq);
 
                irq->enabled = false;
 
@@ -167,10 +195,22 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
                unsigned long flags;
+               bool val;
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
-               if (irq_is_pending(irq))
-                       value |= (1U << i);
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       int err;
+
+                       val = false;
+                       err = irq_get_irqchip_state(irq->host_irq,
+                                                   IRQCHIP_STATE_PENDING,
+                                                   &val);
+                       WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+               } else {
+                       val = irq_is_pending(irq);
+               }
+
+               value |= ((u32)val << i);
                raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
@@ -215,6 +255,21 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
                }
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
+
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       /* HW SGI? Ask the GIC to inject it */
+                       int err;
+                       err = irq_set_irqchip_state(irq->host_irq,
+                                                   IRQCHIP_STATE_PENDING,
+                                                   true);
+                       WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       vgic_put_irq(vcpu->kvm, irq);
+
+                       continue;
+               }
+
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
                else
@@ -269,6 +324,20 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
+               if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+                       /* HW SGI? Ask the GIC to clear its pending bit */
+                       int err;
+                       err = irq_set_irqchip_state(irq->host_irq,
+                                                   IRQCHIP_STATE_PENDING,
+                                                   false);
+                       WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       vgic_put_irq(vcpu->kvm, irq);
+
+                       continue;
+               }
+
                if (irq->hw)
                        vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
                else
@@ -318,8 +387,15 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
 
        raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
-       if (irq->hw) {
+       if (irq->hw && !vgic_irq_is_sgi(irq->intid)) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
+       } else if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+               /*
+                * GICv4.1 VSGI feature doesn't track an active state,
+                * so let's not kid ourselves, there is nothing we can
+                * do here.
+                */
+               irq->active = false;
        } else {
                u32 model = vcpu->kvm->arch.vgic.vgic_model;
                u8 active_source;
@@ -493,6 +569,8 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
                raw_spin_lock_irqsave(&irq->irq_lock, flags);
                /* Narrow the priority range to what we actually support */
                irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+               if (irq->hw && vgic_irq_is_sgi(irq->intid))
+                       vgic_update_vsgi(irq);
                raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
index f45635a6f0ec61222b772c97b51da81371388126..2c9fc13e2c5901fcdfec91ffd0f4e2811172cb4f 100644 (file)
@@ -540,6 +540,8 @@ int vgic_v3_map_resources(struct kvm *kvm)
                goto out;
        }
 
+       if (kvm_vgic_global_state.has_gicv4_1)
+               vgic_v4_configure_vsgis(kvm);
        dist->ready = true;
 
 out:
@@ -595,7 +597,9 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
        /* GICv4 support? */
        if (info->has_v4) {
                kvm_vgic_global_state.has_gicv4 = gicv4_enable;
-               kvm_info("GICv4 support %sabled\n",
+               kvm_vgic_global_state.has_gicv4_1 = info->has_v4_1 && gicv4_enable;
+               kvm_info("GICv4%s support %sabled\n",
+                        kvm_vgic_global_state.has_gicv4_1 ? ".1" : "",
                         gicv4_enable ? "en" : "dis");
        }
 
index 46f875589c472d4181623bbe75412b9bc31bdab2..27ac833e5ec7c2f7fd3c58ab2bde385022f8b629 100644 (file)
  * it. And if we've migrated our vcpu from one CPU to another, we must
  * tell the ITS (so that the messages reach the right redistributor).
  * This is done in two steps: first issue a irq_set_affinity() on the
- * irq corresponding to the vcpu, then call its_schedule_vpe(). You
- * must be in a non-preemptible context. On exit, another call to
- * its_schedule_vpe() tells the redistributor that we're done with the
- * vcpu.
+ * irq corresponding to the vcpu, then call its_make_vpe_resident().
+ * You must be in a non-preemptible context. On exit, a call to
+ * its_make_vpe_non_resident() tells the redistributor that we're done
+ * with the vcpu.
  *
  * Finally, the doorbell handling: Each vcpu is allocated an interrupt
  * which will fire each time a VLPI is made pending whilst the vcpu is
@@ -86,7 +86,8 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
        struct kvm_vcpu *vcpu = info;
 
        /* We got the message, no need to fire again */
-       if (!irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
+       if (!kvm_vgic_global_state.has_gicv4_1 &&
+           !irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
                disable_irq_nosync(irq);
 
        vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
@@ -96,6 +97,104 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
        return IRQ_HANDLED;
 }
 
+static void vgic_v4_sync_sgi_config(struct its_vpe *vpe, struct vgic_irq *irq)
+{
+       vpe->sgi_config[irq->intid].enabled     = irq->enabled;
+       vpe->sgi_config[irq->intid].group       = irq->group;
+       vpe->sgi_config[irq->intid].priority    = irq->priority;
+}
+
+static void vgic_v4_enable_vsgis(struct kvm_vcpu *vcpu)
+{
+       struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+       int i;
+
+       /*
+        * With GICv4.1, every virtual SGI can be directly injected. So
+        * let's pretend that they are HW interrupts, tied to a host
+        * IRQ. The SGI code will do its magic.
+        */
+       for (i = 0; i < VGIC_NR_SGIS; i++) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+               struct irq_desc *desc;
+               unsigned long flags;
+               int ret;
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+
+               if (irq->hw)
+                       goto unlock;
+
+               irq->hw = true;
+               irq->host_irq = irq_find_mapping(vpe->sgi_domain, i);
+
+               /* Transfer the full irq state to the vPE */
+               vgic_v4_sync_sgi_config(vpe, irq);
+               desc = irq_to_desc(irq->host_irq);
+               ret = irq_domain_activate_irq(irq_desc_get_irq_data(desc),
+                                             false);
+               if (!WARN_ON(ret)) {
+                       /* Transfer pending state */
+                       ret = irq_set_irqchip_state(irq->host_irq,
+                                                   IRQCHIP_STATE_PENDING,
+                                                   irq->pending_latch);
+                       WARN_ON(ret);
+                       irq->pending_latch = false;
+               }
+       unlock:
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+}
+
+static void vgic_v4_disable_vsgis(struct kvm_vcpu *vcpu)
+{
+       int i;
+
+       for (i = 0; i < VGIC_NR_SGIS; i++) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+               struct irq_desc *desc;
+               unsigned long flags;
+               int ret;
+
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
+
+               if (!irq->hw)
+                       goto unlock;
+
+               irq->hw = false;
+               ret = irq_get_irqchip_state(irq->host_irq,
+                                           IRQCHIP_STATE_PENDING,
+                                           &irq->pending_latch);
+               WARN_ON(ret);
+
+               desc = irq_to_desc(irq->host_irq);
+               irq_domain_deactivate_irq(irq_desc_get_irq_data(desc));
+       unlock:
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+}
+
+/* Must be called with the kvm lock held */
+void vgic_v4_configure_vsgis(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       kvm_arm_halt_guest(kvm);
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (dist->nassgireq)
+                       vgic_v4_enable_vsgis(vcpu);
+               else
+                       vgic_v4_disable_vsgis(vcpu);
+       }
+
+       kvm_arm_resume_guest(kvm);
+}
+
 /**
  * vgic_v4_init - Initialize the GICv4 data structures
  * @kvm:       Pointer to the VM being initialized
@@ -140,6 +239,7 @@ int vgic_v4_init(struct kvm *kvm)
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
                int irq = dist->its_vm.vpes[i]->irq;
+               unsigned long irq_flags = DB_IRQ_FLAGS;
 
                /*
                 * Don't automatically enable the doorbell, as we're
@@ -147,8 +247,14 @@ int vgic_v4_init(struct kvm *kvm)
                 * blocked. Also disable the lazy disabling, as the
                 * doorbell could kick us out of the guest too
                 * early...
+                *
+                * On GICv4.1, the doorbell is managed in HW and must
+                * be left enabled.
                 */
-               irq_set_status_flags(irq, DB_IRQ_FLAGS);
+               if (kvm_vgic_global_state.has_gicv4_1)
+                       irq_flags &= ~IRQ_NOAUTOEN;
+               irq_set_status_flags(irq, irq_flags);
+
                ret = request_irq(irq, vgic_v4_doorbell_handler,
                                  0, "vcpu", vcpu);
                if (ret) {
@@ -199,19 +305,11 @@ void vgic_v4_teardown(struct kvm *kvm)
 int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
 {
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
-       struct irq_desc *desc = irq_to_desc(vpe->irq);
 
        if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
                return 0;
 
-       /*
-        * If blocking, a doorbell is required. Undo the nested
-        * disable_irq() calls...
-        */
-       while (need_db && irqd_irq_disabled(&desc->irq_data))
-               enable_irq(vpe->irq);
-
-       return its_schedule_vpe(vpe, false);
+       return its_make_vpe_non_resident(vpe, need_db);
 }
 
 int vgic_v4_load(struct kvm_vcpu *vcpu)
@@ -232,18 +330,19 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
        if (err)
                return err;
 
-       /* Disabled the doorbell, as we're about to enter the guest */
-       disable_irq_nosync(vpe->irq);
-
-       err = its_schedule_vpe(vpe, true);
+       err = its_make_vpe_resident(vpe, false, vcpu->kvm->arch.vgic.enabled);
        if (err)
                return err;
 
        /*
         * Now that the VPE is resident, let's get rid of a potential
-        * doorbell interrupt that would still be pending.
+        * doorbell interrupt that would still be pending. This is a
+        * GICv4.0 only "feature"...
         */
-       return irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+       if (!kvm_vgic_global_state.has_gicv4_1)
+               err = irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+
+       return err;
 }
 
 static struct vgic_its *vgic_get_its(struct kvm *kvm,
index c7fefd6b1c8071083a956b4c097e08fa6e7efdff..769e4802645ee8ef30f3761ba7c0ddc73bf652b2 100644 (file)
@@ -316,5 +316,6 @@ void vgic_its_invalidate_cache(struct kvm *kvm);
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);
 void vgic_v4_teardown(struct kvm *kvm);
+void vgic_v4_configure_vsgis(struct kvm *kvm);
 
 #endif
index 28eae681859f7f5cd9c07660900c14ecfd2c01ab..f744bc603c5347aa48f0cdb568147152078d25f7 100644 (file)
@@ -882,6 +882,9 @@ static inline void kvm_memslot_delete(struct kvm_memslots *slots,
 
        slots->used_slots--;
 
+       if (atomic_read(&slots->lru_slot) >= slots->used_slots)
+               atomic_set(&slots->lru_slot, 0);
+
        for (i = slots->id_to_index[memslot->id]; i < slots->used_slots; i++) {
                mslots[i] = mslots[i + 1];
                slots->id_to_index[mslots[i].id] = i;