Merge tag 'kbuild-fixes-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahi...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Dec 2019 18:49:47 +0000 (10:49 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Dec 2019 18:49:47 +0000 (10:49 -0800)
Pull Kbuild fixes from Masahiro Yamada:

 - fix warning in out-of-tree 'make clean'

 - add READELF variable to the top Makefile

 - fix broken builds when LINUX_COMPILE_BY contains a backslash

 - fix build warning in kallsyms

 - fix NULL pointer access in expr_eq() in Kconfig

 - fix missing dependency on rsync in deb-pkg build

 - remove ---help--- from documentation

 - fix misleading documentation about directory descending

* tag 'kbuild-fixes-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild:
  kbuild: clarify the difference between obj-y and obj-m w.r.t. descending
  kconfig: remove ---help--- from documentation
  scripts: package: mkdebian: add missing rsync dependency
  kconfig: don't crash on NULL expressions in expr_eq()
  scripts/kallsyms: fix offset overflow of kallsyms_relative_base
  mkcompile_h: use printf for LINUX_COMPILE_BY
  mkcompile_h: git rid of UTS_TRUNCATE from LINUX_COMPILE_{BY,HOST}
  x86/boot: kbuild: allow readelf executable to be specified
  kbuild: fix 'No such file or directory' warning when cleaning

724 files changed:
.mailmap
Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
Documentation/admin-guide/device-mapper/dm-integrity.rst
Documentation/admin-guide/device-mapper/index.rst
Documentation/dev-tools/kselftest.rst
Documentation/dev-tools/kunit/index.rst
Documentation/dev-tools/kunit/kunit-tool.rst [new file with mode: 0644]
Documentation/dev-tools/kunit/start.rst
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/arm/sunxi.yaml
Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
Documentation/devicetree/bindings/crypto/allwinner,sun4i-a10-crypto.yaml
Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
Documentation/devicetree/bindings/display/panel/ronbo,rb070d30.yaml
Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
Documentation/devicetree/bindings/i2c/allwinner,sun6i-a31-p2wi.yaml
Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml
Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-a10-ic.yaml
Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml
Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml
Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
Documentation/devicetree/bindings/net/allwinner,sun4i-a10-emac.yaml
Documentation/devicetree/bindings/net/allwinner,sun4i-a10-mdio.yaml
Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml
Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml
Documentation/devicetree/bindings/net/snps,dwmac.yaml
Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml
Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
Documentation/devicetree/bindings/rtc/allwinner,sun4i-a10-rtc.yaml
Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
Documentation/devicetree/bindings/serio/allwinner,sun4i-a10-ps2.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
Documentation/devicetree/bindings/sound/allwinner,sun50i-a64-codec-analog.yaml
Documentation/devicetree/bindings/sound/allwinner,sun8i-a23-codec-analog.yaml
Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml
Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
Documentation/devicetree/bindings/timer/allwinner,sun4i-a10-timer.yaml
Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml
Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
Documentation/filesystems/erofs.txt
Documentation/filesystems/overlayfs.rst [moved from Documentation/filesystems/overlayfs.txt with 99% similarity]
Documentation/process/coding-style.rst
Documentation/scsi/smartpqi.txt
Documentation/translations/it_IT/process/coding-style.rst
Documentation/translations/zh_CN/process/coding-style.rst
MAINTAINERS
Makefile
arch/arc/kernel/unwind.c
arch/arm/boot/dts/am335x-sancloud-bbe.dts
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm2711.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/e60k02.dtsi
arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
arch/arm/configs/exynos_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/crypto/curve25519-glue.c
arch/arm/mach-bcm/bcm2711.c
arch/arm/mach-imx/cpu.c
arch/arm/mach-mmp/pxa168.h
arch/arm/mach-vexpress/spc.c
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/kernel/cpu_errata.c
arch/mips/cavium-octeon/executive/cvmx-bootmem.c
arch/nios2/mm/ioremap.c
arch/parisc/include/asm/cmpxchg.h
arch/parisc/include/asm/kexec.h
arch/parisc/kernel/Makefile
arch/parisc/kernel/drivers.c
arch/parisc/kernel/pdt.c
arch/powerpc/include/asm/spinlock.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/irq.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/lib/string_32.S
arch/powerpc/lib/string_64.S
arch/powerpc/mm/mem.c
arch/powerpc/mm/nohash/8xx.c
arch/powerpc/net/bpf_jit32.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/pseries/cmm.c
arch/powerpc/platforms/pseries/setup.c
arch/riscv/Kconfig.socs
arch/riscv/boot/Makefile
arch/s390/Kconfig
arch/s390/include/asm/setup.h
arch/s390/include/asm/uv.h
arch/s390/kernel/early.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/smp.c
arch/s390/lib/spinlock.c
arch/s390/lib/test_unwind.c
arch/s390/mm/kasan_init.c
arch/sh/drivers/platform_early.c
arch/sh/kernel/kgdb.c
arch/sparc/net/bpf_jit_comp_32.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/ftrace.c
arch/x86/platform/efi/quirks.c
block/bio.c
block/blk-cgroup.c
block/blk-core.c
crypto/adiantum.c
crypto/asymmetric_keys/asym_tpm.c
crypto/asymmetric_keys/public_key.c
crypto/essiv.c
drivers/acpi/device_pm.c
drivers/android/binder.c
drivers/base/devtmpfs.c
drivers/base/platform.c
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bus/ti-sysc.c
drivers/char/random.c
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_ftpm_tee.c
drivers/char/tpm/tpm_tis_core.c
drivers/clk/at91/at91sam9260.c
drivers/clk/at91/at91sam9rl.c
drivers/clk/at91/at91sam9x5.c
drivers/clk/at91/pmc.c
drivers/clk/at91/sama5d2.c
drivers/clk/at91/sama5d4.c
drivers/clk/clk.c
drivers/clk/imx/clk-composite-8m.c
drivers/clk/imx/clk-imx7ulp.c
drivers/clk/imx/clk-pll14xx.c
drivers/clk/qcom/gcc-sc7180.c
drivers/clk/qcom/gpucc-msm8998.c
drivers/cpufreq/vexpress-spc-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/devfreq/devfreq.c
drivers/dma-buf/sync_file.c
drivers/firmware/efi/earlycon.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/gop.c
drivers/firmware/efi/rci2-table.c
drivers/gpio/gpiolib-of.c
drivers/gpu/drm/amd/acp/Kconfig
drivers/gpu/drm/amd/amdgpu/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/df_v3_6.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
drivers/gpu/drm/amd/display/dc/dcn20/Makefile
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn21/Makefile
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dsc/Makefile
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/include/i2caux_interface.h
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_hdcp.h
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_scheduler.c
drivers/gpu/drm/i915/i915_sw_fence_work.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mcde/mcde_dsi.c
drivers/gpu/drm/meson/meson_venc_cvbs.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/nouveau/dispnv50/atom.h
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/panfrost/panfrost_devfreq.c
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/panfrost/panfrost_gem.c
drivers/gpu/drm/panfrost/panfrost_gem.h
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
drivers/gpu/drm/panfrost/panfrost_perfcnt.h
drivers/hwtracing/intel_th/core.c
drivers/hwtracing/intel_th/intel_th.h
drivers/hwtracing/intel_th/msu.c
drivers/hwtracing/intel_th/pci.c
drivers/i2c/i2c-core-base.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/ad7124.c
drivers/iio/adc/ad7606.c
drivers/iio/adc/ad7949.c
drivers/iio/adc/intel_mrfld_adc.c
drivers/iio/adc/max1027.c
drivers/iio/adc/max9611.c
drivers/iio/humidity/hdc100x.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/temperature/ltc2983.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/counters.c
drivers/infiniband/core/ib_core_uverbs.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/infiniband/hw/hfi1/verbs.h
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/cmd.c
drivers/infiniband/hw/mlx5/cmd.h
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/sw/rxe/rxe_recv.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
drivers/interconnect/qcom/Kconfig
drivers/interconnect/qcom/msm8974.c
drivers/interconnect/qcom/qcs404.c
drivers/interconnect/qcom/sdm845.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/iommu.c
drivers/iommu/iova.c
drivers/md/dm-clone-metadata.c
drivers/md/dm-clone-metadata.h
drivers/md/dm-clone-target.c
drivers/md/dm-mpath.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/raid1.c
drivers/md/raid5-ppl.c
drivers/md/raid5.c
drivers/media/platform/omap3isp/isppreview.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/context.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/ocxl/context.c
drivers/misc/ocxl/file.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/cavium/liquidio/octeon_console.c
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igc/igc_ethtool.c
drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
drivers/net/ethernet/intel/ixgbevf/ethtool.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/netronome/nfp/bpf/jit.c
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/bpf/offload.c
drivers/net/ethernet/netronome/nfp/flower/main.h
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/realtek/r8169_firmware.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/ti/cpsw_ethtool.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/fjes/fjes_ethtool.c
drivers/net/geneve.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/usb/sierra_net.c
drivers/net/usb/usbnet.c
drivers/net/vxlan.c
drivers/net/wireless/marvell/libertas/debugfs.c
drivers/net/wireless/marvell/mwifiex/util.h
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/fcloop.c
drivers/nvme/target/loop.c
drivers/of/platform.c
drivers/pci/controller/pcie-rockchip-host.c
drivers/perf/arm_smmuv3_pmu.c
drivers/pinctrl/Kconfig
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/pinctrl-ingenic.c
drivers/pinctrl/pinmux.c
drivers/platform/mellanox/mlxbf-bootctl.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/pcengines-apuv2.c
drivers/platform/x86/pmc_atom.c
drivers/regulator/core.c
drivers/regulator/max77650-regulator.c
drivers/regulator/rn5t618-regulator.c
drivers/regulator/s5m8767.c
drivers/reset/core.c
drivers/reset/reset-brcmstb.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_mpc.h
drivers/scsi/aacraid/aachba.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/smartpqi/smartpqi_init.c
drivers/scsi/ufs/cdns-pltfrm.c
drivers/scsi/ufs/ufs_bsg.c
drivers/spi/spi-cadence.c
drivers/spi/spi-cavium-thunderx.c
drivers/spi/spi-dw.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-nxp-fspi.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-sprd.c
drivers/spi/spi-ti-qspi.c
drivers/staging/axis-fifo/Kconfig
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/exfat/exfat.h
drivers/staging/exfat/exfat_core.c
drivers/staging/exfat/exfat_super.c
drivers/staging/fbtft/fb_uc1611.c
drivers/staging/fbtft/fb_watterott.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/hp/Kconfig
drivers/staging/isdn/gigaset/usb-gigaset.c
drivers/staging/octeon/Kconfig
drivers/staging/qlge/qlge_ethtool.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8712/usb_intf.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/staging/wfx/data_tx.c
drivers/staging/wfx/data_tx.h
drivers/staging/wfx/hif_tx_mib.h
drivers/staging/wfx/main.c
drivers/staging/wfx/queue.c
drivers/staging/wfx/sta.c
drivers/staging/wlan-ng/Kconfig
drivers/target/iscsi/cxgbit/cxgbit_main.c
drivers/thermal/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/msm_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sprd_serial.c
drivers/tty/tty_port.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/common/usb-conn-gpio.c
drivers/usb/core/hcd.c
drivers/usb/core/urb.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_ecm.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_rndis.c
drivers/usb/host/ehci-q.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/adutux.c
drivers/usb/misc/idmouse.c
drivers/usb/mon/mon_bin.c
drivers/usb/roles/class.c
drivers/usb/serial/io_edgeport.c
drivers/usb/storage/scsiglue.c
drivers/usb/typec/class.c
drivers/usb/typec/tcpm/Kconfig
drivers/usb/usbip/usbip_common.c
drivers/usb/usbip/vhci_rx.c
drivers/virtio/virtio_balloon.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/xenbus/xenbus.h
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenbus/xenbus_probe_backend.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/afs/dynroot.c
fs/afs/mntpt.c
fs/afs/proc.c
fs/afs/server.c
fs/afs/super.c
fs/btrfs/Kconfig
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/send.c
fs/btrfs/tests/free-space-tree-tests.c
fs/btrfs/tests/qgroup-tests.c
fs/btrfs/tree-checker.c
fs/btrfs/tree-log.c
fs/btrfs/uuid-tree.c
fs/btrfs/volumes.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mdsmap.c
fs/ceph/super.c
fs/ceph/super.h
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2proto.h
fs/crypto/keyring.c
fs/erofs/xattr.c
fs/ext4/inode-test.c
fs/file.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/namespace.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/export.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/pipe.c
fs/proc/stat.c
fs/verity/enable.c
include/linux/blk-cgroup.h
include/linux/cpufreq.h
include/linux/devfreq.h
include/linux/device.h
include/linux/efi.h
include/linux/filter.h
include/linux/ftrace.h
include/linux/i2c.h
include/linux/initrd.h
include/linux/kasan.h
include/linux/kvm_host.h
include/linux/mm.h
include/linux/nvme-fc-driver.h
include/linux/phy_led_triggers.h
include/linux/platform_data/ti-sysc.h
include/linux/printk.h
include/linux/sched/cpufreq.h
include/linux/syscalls.h
include/linux/tpm.h
include/net/garp.h
include/net/ip_tunnels.h
include/net/mrp.h
include/net/netfilter/nf_conntrack_helper.h
include/net/netfilter/nf_tables_core.h
include/net/sock.h
include/rdma/ib_verbs.h
include/sound/soc.h
include/uapi/linux/io_uring.h
include/xen/interface/io/ring.h
include/xen/xenbus.h
init/do_mounts.c
init/do_mounts_initrd.c
init/main.c
ipc/util.c
kernel/bpf/cgroup.c
kernel/bpf/local_storage.c
kernel/locking/mutex.c
kernel/locking/spinlock_debug.c
kernel/module.c
kernel/sched/cpufreq.c
kernel/sched/cpufreq_schedutil.c
kernel/trace/fgraph.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events_inject.c
kernel/workqueue.c
lib/Kconfig.debug
lib/raid6/unroll.awk
mm/kasan/common.c
mm/memory.c
mm/vmalloc.c
mm/vmscan.c
net/802/mrp.c
net/batman-adv/main.c
net/bpf/test_run.c
net/bridge/br.c
net/core/dev.c
net/core/filter.c
net/core/flow_dissector.c
net/core/xdp.c
net/dccp/proto.c
net/ipv4/ip_gre.c
net/ipv4/ip_vti.c
net/ipv4/tcp.c
net/ipv6/ip6_gre.c
net/iucv/af_iucv.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nft_ct.c
net/netfilter/nft_masq.c
net/netfilter/nft_nat.c
net/netfilter/nft_redir.c
net/netfilter/nft_tproxy.c
net/netfilter/xt_RATEEST.c
net/netlink/af_netlink.c
net/openvswitch/datapath.c
net/openvswitch/flow.h
net/rxrpc/af_rxrpc.c
net/sched/act_ct.c
net/sched/cls_flower.c
net/socket.c
net/unix/af_unix.c
scripts/checkpatch.pl
security/integrity/ima/ima_policy.c
security/keys/Kconfig
security/keys/Makefile
security/keys/compat.c
security/keys/internal.h
security/keys/trusted-keys/trusted_tpm2.c
sound/core/pcm_native.c
sound/firewire/fireface/ff-pcm.c
sound/firewire/motu/motu-pcm.c
sound/firewire/oxfw/oxfw-pcm.c
sound/hda/hdac_stream.c
sound/pci/echoaudio/echoaudio_dsp.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/max98090.c
sound/soc/codecs/max98090.h
sound/soc/codecs/rt5677-spi.h
sound/soc/codecs/rt5682.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8962.c
sound/soc/generic/simple-card.c
sound/soc/intel/atom/sst/sst.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/common/soc-acpi-intel-cml-match.c
sound/soc/soc-compress.c
sound/soc/soc-core.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/byt.c
sound/soc/sof/loader.c
sound/soc/sof/topology.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/lib/memcpy_64.S
tools/arch/x86/lib/memset_64.S
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/stat.h
tools/lib/traceevent/Makefile
tools/lib/traceevent/plugins/Makefile
tools/perf/Documentation/perf-kvm.txt
tools/perf/arch/arm/tests/regs_load.S
tools/perf/arch/arm64/tests/regs_load.S
tools/perf/arch/x86/tests/regs_load.S
tools/perf/builtin-inject.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/check-headers.sh
tools/perf/lib/cpumap.c
tools/perf/lib/evlist.c
tools/perf/lib/evsel.c
tools/perf/lib/include/internal/evlist.h
tools/perf/lib/include/perf/cpumap.h
tools/perf/lib/include/perf/evsel.h
tools/perf/pmu-events/arch/s390/cf_z13/extended.json
tools/perf/pmu-events/arch/s390/cf_z14/extended.json
tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
tools/perf/tests/Build
tools/perf/tests/builtin-test.c
tools/perf/tests/cpumap.c
tools/perf/tests/event-times.c
tools/perf/tests/genelf.c [new file with mode: 0644]
tools/perf/tests/tests.h
tools/perf/trace/beauty/clone.c
tools/perf/util/cpumap.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/genelf.c
tools/perf/util/header.c
tools/perf/util/include/linux/linkage.h
tools/perf/util/machine.c
tools/perf/util/metricgroup.c
tools/perf/util/sort.c
tools/perf/util/stat.c
tools/perf/util/stat.h
tools/testing/kunit/kunit_tool_test.py
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
tools/testing/selftests/kselftest/module.sh
tools/testing/selftests/kselftest/prefix.pl
tools/testing/selftests/kselftest/runner.sh
tools/testing/selftests/safesetid/Makefile
tools/testing/selftests/safesetid/safesetid-test.c
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/tpm2.py
tools/testing/selftests/tpm2/tpm2_tests.py

index c24773d..b37212c 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -152,6 +152,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
+Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
 Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>
 Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
@@ -276,3 +277,5 @@ Gustavo Padovan <gustavo@las.ic.unicamp.br>
 Gustavo Padovan <padovan@profusion.mobi>
 Changbin Du <changbin.du@intel.com> <changbin.du@intel.com>
 Changbin Du <changbin.du@intel.com> <changbin.du@gmail.com>
+Steve Wise <larrystevenwise@gmail.com> <swise@chelsio.com>
+Steve Wise <larrystevenwise@gmail.com> <swise@opengridcomputing.com>
index c65a805..401d202 100644 (file)
@@ -1,4 +1,4 @@
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/lifecycle_state
+What:          /sys/bus/platform/devices/MLNXBF04:00/lifecycle_state
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -10,7 +10,7 @@ Description:
                  GA Non-Secured - Non-Secure chip and not able to change state
                  RMA - Return Merchandise Authorization
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/post_reset_wdog
+What:          /sys/bus/platform/devices/MLNXBF04:00/post_reset_wdog
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -19,7 +19,7 @@ Description:
                to reboot the chip and recover it to the old state if the new
                boot partition fails.
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/reset_action
+What:          /sys/bus/platform/devices/MLNXBF04:00/reset_action
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -30,7 +30,7 @@ Description:
                  emmc - boot from the onchip eMMC
                  emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/second_reset_action
+What:          /sys/bus/platform/devices/MLNXBF04:00/second_reset_action
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -44,7 +44,7 @@ Description:
                  swap_emmc - swap the primary / secondary boot partition
                  none - cancel the action
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/secure_boot_fuse_state
+What:          /sys/bus/platform/devices/MLNXBF04:00/secure_boot_fuse_state
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
index 594095b..c00f9f1 100644 (file)
@@ -144,7 +144,7 @@ journal_crypt:algorithm(:key)       (the key is optional)
        Encrypt the journal using given algorithm to make sure that the
        attacker can't read the journal. You can use a block cipher here
        (such as "cbc(aes)") or a stream cipher (for example "chacha20",
-       "salsa20", "ctr(aes)" or "ecb(arc4)").
+       "salsa20" or "ctr(aes)").
 
        The journal contains history of last writes to the block device,
        an attacker reading the journal could see the last sector nubmers
index 4872fb6..ec62fcc 100644 (file)
@@ -8,6 +8,7 @@ Device Mapper
     cache-policies
     cache
     delay
+    dm-clone
     dm-crypt
     dm-dust
     dm-flakey
index ecdfdc9..61ae13c 100644 (file)
@@ -203,12 +203,12 @@ Test Module
 Kselftest tests the kernel from userspace.  Sometimes things need
 testing from within the kernel, one method of doing this is to create a
 test module.  We can tie the module into the kselftest framework by
-using a shell script test runner.  ``kselftest_module.sh`` is designed
+using a shell script test runner.  ``kselftest/module.sh`` is designed
 to facilitate this process.  There is also a header file provided to
 assist writing kernel modules that are for use with kselftest:
 
 - ``tools/testing/kselftest/kselftest_module.h``
-- ``tools/testing/kselftest/kselftest_module.sh``
+- ``tools/testing/kselftest/kselftest/module.sh``
 
 How to use
 ----------
@@ -247,7 +247,7 @@ A bare bones test module might look like this:
 
    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-   #include "../tools/testing/selftests/kselftest_module.h"
+   #include "../tools/testing/selftests/kselftest/module.h"
 
    KSTM_MODULE_GLOBALS();
 
@@ -276,7 +276,7 @@ Example test script
 
     #!/bin/bash
     # SPDX-License-Identifier: GPL-2.0+
-    $(dirname $0)/../kselftest_module.sh "foo" test_foo
+    $(dirname $0)/../kselftest/module.sh "foo" test_foo
 
 
 Test Harness
index 26ffb46..c60d760 100644 (file)
@@ -9,6 +9,7 @@ KUnit - Unit Testing for the Linux Kernel
 
        start
        usage
+       kunit-tool
        api/index
        faq
 
diff --git a/Documentation/dev-tools/kunit/kunit-tool.rst b/Documentation/dev-tools/kunit/kunit-tool.rst
new file mode 100644 (file)
index 0000000..50d4639
--- /dev/null
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+kunit_tool How-To
+=================
+
+What is kunit_tool?
+===================
+
+kunit_tool is a script (``tools/testing/kunit/kunit.py``) that aids in building
+the Linux kernel as UML (`User Mode Linux
+<http://user-mode-linux.sourceforge.net/>`_), running KUnit tests, parsing
+the test results and displaying them in a user friendly manner.
+
+What is a kunitconfig?
+======================
+
+It's just a defconfig that kunit_tool looks for in the base directory.
+kunit_tool uses it to generate a .config as you might expect. In addition, it
+verifies that the generated .config contains the CONFIG options in the
+kunitconfig; the reason it does this is so that it is easy to be sure that a
+CONFIG that enables a test actually ends up in the .config.
+
+How do I use kunit_tool?
+========================
+
+If a kunitconfig is present at the root directory, all you have to do is:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run
+
+However, you most likely want to use it with the following options:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --timeout=30 --jobs=`nproc --all`
+
+- ``--timeout`` sets a maximum amount of time to allow tests to run.
+- ``--jobs`` sets the number of threads to use to build the kernel.
+
+If you just want to use the defconfig that ships with the kernel, you can
+append the ``--defconfig`` flag as well:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --timeout=30 --jobs=`nproc --all` --defconfig
+
+.. note::
+       This command is particularly helpful for getting started because it
+       just works. No kunitconfig needs to be present.
+
+For a list of all the flags supported by kunit_tool, you can run:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --help
index aeeddfa..9d6db89 100644 (file)
@@ -19,11 +19,14 @@ The wrapper can be run with:
 
 .. code-block:: bash
 
-   ./tools/testing/kunit/kunit.py run
+       ./tools/testing/kunit/kunit.py run --defconfig
+
+For more information on this wrapper (also called kunit_tool) checkout the
+:doc:`kunit-tool` page.
 
 Creating a kunitconfig
 ======================
-The Python script is a thin wrapper around Kbuild as such, it needs to be
+The Python script is a thin wrapper around Kbuild. As such, it needs to be
 configured with a ``kunitconfig`` file. This file essentially contains the
 regular Kernel config, with the specific test targets as well.
 
@@ -59,8 +62,8 @@ If everything worked correctly, you should see the following:
 followed by a list of tests that are run. All of them should be passing.
 
 .. note::
-   Because it is building a lot of sources for the first time, the ``Building
-   kunit kernel`` step may take a while.
+       Because it is building a lot of sources for the first time, the
+       ``Building KUnit kernel`` step may take a while.
 
 Writing your first test
 =======================
@@ -159,7 +162,7 @@ Now you can run the test:
 
 .. code-block:: bash
 
-       ./tools/testing/kunit/kunit.py
+       ./tools/testing/kunit/kunit.py run
 
 You should see the following failure:
 
index c6e6963..b9a065a 100644 (file)
@@ -16,7 +16,7 @@ Organization of this document
 =============================
 
 This document is organized into two main sections: Testing and Isolating
-Behavior. The first covers what a unit test is and how to use KUnit to write
+Behavior. The first covers what unit tests are and how to use KUnit to write
 them. The second covers how to use KUnit to isolate code and make it possible
 to unit test code that was otherwise un-unit-testable.
 
@@ -174,13 +174,13 @@ Test Suites
 ~~~~~~~~~~~
 
 Now obviously one unit test isn't very helpful; the power comes from having
-many test cases covering all of your behaviors. Consequently it is common to
-have many *similar* tests; in order to reduce duplication in these closely
-related tests most unit testing frameworks provide the concept of a *test
-suite*, in KUnit we call it a *test suite*; all it is is just a collection of
-test cases for a unit of code with a set up function that gets invoked before
-every test cases and then a tear down function that gets invoked after every
-test case completes.
+many test cases covering all of a unit's behaviors. Consequently it is common
+to have many *similar* tests; in order to reduce duplication in these closely
+related tests most unit testing frameworks - including KUnit - provide the
+concept of a *test suite*. A *test suite* is just a collection of test cases
+for a unit of code with a set up function that gets invoked before every test
+case and then a tear down function that gets invoked after every test case
+completes.
 
 Example:
 
@@ -211,7 +211,7 @@ KUnit test framework.
 .. note::
    A test case will only be run if it is associated with a test suite.
 
-For more information on these types of things see the :doc:`api/test`.
+For more information on these types of things see the :doc:`api/test`.
 
 Isolating Behavior
 ==================
@@ -338,7 +338,7 @@ We can easily test this code by *faking out* the underlying EEPROM:
                return count;
        }
 
-       ssize_t fake_eeprom_write(struct eeprom *this, size_t offset, const char *buffer, size_t count)
+       ssize_t fake_eeprom_write(struct eeprom *parent, size_t offset, const char *buffer, size_t count)
        {
                struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent);
 
@@ -454,7 +454,7 @@ KUnit on non-UML architectures
 By default KUnit uses UML as a way to provide dependencies for code under test.
 Under most circumstances KUnit's usage of UML should be treated as an
 implementation detail of how KUnit works under the hood. Nevertheless, there
-are instances where being able to run architecture specific code, or test
+are instances where being able to run architecture specific code or test
 against real hardware is desirable. For these reasons KUnit supports running on
 other architectures.
 
@@ -557,7 +557,7 @@ run your tests on your hardware setup just by compiling for your architecture.
 .. important::
    Always prefer tests that run on UML to tests that only run under a particular
    architecture, and always prefer tests that run under QEMU or another easy
-   (and monitarily free) to obtain software environment to a specific piece of
+   (and monetarily free) to obtain software environment to a specific piece of
    hardware.
 
 Nevertheless, there are still valid reasons to write an architecture or hardware
index 8a1e38a..cffe8bb 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner platforms device tree bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   $nodename:
index d2a8722..f0b3d30 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 Display Engine Bus Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   $nodename:
index be32f08..9fe11ce 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A23 RSB Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells":
index 64938fd..4d38212 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner Clock Control Unit Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#clock-cells":
index 80b3e73..33c7842 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Security System Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index dafc098..0f70749 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 MIPI-DSI Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index 0e7987f..d67617f 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Ronbo RB070D30 DSI Display Panel
 
 maintainers:
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 15abc0f..8380819 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 387d599..9e53472 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 740b7f9..c1676b9 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 9346ef6..6097e8a 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 P2WI (Push/Pull 2 Wires Interface) Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/i2c/i2c-controller.yaml#
index b68be3a..e1f6d64 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/iio/adc/adi,ad7292.yaml#
@@ -53,7 +53,8 @@ patternProperties:
         description: |
           The channel number. It can have up to 8 channels numbered from 0 to 7.
         items:
-          maximum: 7
+          - minimum: 0
+            maximum: 7
 
       diff-channels:
         description: see Documentation/devicetree/bindings/iio/adc/adc.txt
index d74962c..15c514b 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A33 Thermal Sensor Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#io-channel-cells":
index b3bd8ef..5b3b71c 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 LRADC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 23a202d..953d875 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Interrupt Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/interrupt-controller.yaml#
index 8cd08cf..cf09055 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A20 Non-Maskable Interrupt Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/interrupt-controller.yaml#
index d3e423f..0f6374c 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 description: |-
   The Allwinner A10 and later has a CMOS Sensor Interface to retrieve
index dea36d6..7838804 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Infrared Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "rc.yaml#"
index 30d9fb1..22a94b6 100644 (file)
@@ -60,7 +60,8 @@ patternProperties:
             maximum: 1066000000
 
           nvidia,emem-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description: |
               Values to be written to the EMEM register block. See section
               "15.6.1 MC Registers" in the TRM.
index 7fe0ca1..e4135ba 100644 (file)
@@ -56,7 +56,8 @@ patternProperties:
             maximum: 900000000
 
           nvidia,emc-auto-cal-interval:
-            $ref: /schemas/types.yaml#/definitions/uint32
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
             description:
               Pad calibration interval in microseconds.
             minimum: 0
@@ -78,7 +79,8 @@ patternProperties:
               Mode Register 0.
 
           nvidia,emc-zcal-cnt-long:
-            $ref: /schemas/types.yaml#/definitions/uint32
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
             description:
               Number of EMC clocks to wait before issuing any commands after
               sending ZCAL_MRW_CMD.
@@ -96,7 +98,8 @@ patternProperties:
               FBIO "read" FIFO periodic resetting enabled.
 
           nvidia,emc-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description:
               EMC timing characterization data. These are the registers
               (see section "18.13.2 EMC Registers" in the TRM) whose values
index 84fd57b..4b9196c 100644 (file)
@@ -77,7 +77,8 @@ patternProperties:
             maximum: 900000000
 
           nvidia,emem-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description: |
               Values to be written to the EMEM register block. See section
               "18.13.1 MC Registers" in the TRM.
index 4b1a09a..39afacc 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Resistive Touchscreen Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#thermal-sensor-cells":
index 64bca41..e82c9a0 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index b5b3cf5..5d3fa41 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index ae4796e..8d8560a 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index e5562c5..767193e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 MDIO Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "mdio.yaml#"
index f683b71..703d0d8 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 11654d4..db36b4d 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A83t EMAC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 770af7c..a95960e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 CAN Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 4845e29..e08cd4c 100644 (file)
@@ -347,6 +347,7 @@ allOf:
               - st,spear600-gmac
 
     then:
+      properties:
         snps,tso:
           $ref: /schemas/types.yaml#definitions/flag
           description:
index 81ae8ca..ac8c763 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/net/ti,cpsw-switch.yaml#
@@ -44,7 +44,6 @@ properties:
     description: CPSW functional clock
 
   clock-names:
-    maxItems: 1
     items:
       - const: fck
 
@@ -70,7 +69,6 @@ properties:
       Phandle to the system control device node which provides access to
       efuse IO range with MAC addresses
 
-
   ethernet-ports:
     type: object
     properties:
@@ -82,8 +80,6 @@ properties:
     patternProperties:
       "^port@[0-9]+$":
           type: object
-          minItems: 1
-          maxItems: 2
           description: CPSW external ports
 
           allOf:
@@ -91,23 +87,20 @@ properties:
 
           properties:
             reg:
-              maxItems: 1
-              enum: [1, 2]
+              items:
+                - enum: [1, 2]
               description: CPSW port number
 
             phys:
-              $ref: /schemas/types.yaml#definitions/phandle-array
               maxItems: 1
               description:  phandle on phy-gmii-sel PHY
 
             label:
-              $ref: /schemas/types.yaml#/definitions/string-array
-              maxItems: 1
               description: label associated with this port
 
             ti,dual-emac-pvid:
-              $ref: /schemas/types.yaml#/definitions/uint32
-              maxItems: 1
+              allOf:
+                - $ref: /schemas/types.yaml#/definitions/uint32
               minimum: 1
               maximum: 1024
               description:
@@ -136,7 +129,6 @@ properties:
         description: CPTS reference clock
 
       clock-names:
-        maxItems: 1
         items:
           - const: cpts
 
@@ -201,7 +193,7 @@ examples:
                         phys = <&phy_gmii_sel 1>;
                         phy-handle = <&ethphy0_sw>;
                         phy-mode = "rgmii";
-                        ti,dual_emac_pvid = <1>;
+                        ti,dual-emac-pvid = <1>;
                 };
 
                 cpsw_port2: port@2 {
@@ -211,7 +203,7 @@ examples:
                         phys = <&phy_gmii_sel 2>;
                         phy-handle = <&ethphy1_sw>;
                         phy-mode = "rgmii";
-                        ti,dual_emac_pvid = <2>;
+                        ti,dual-emac-pvid = <2>;
                 };
         };
 
index 659b020..daf1321 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Security ID Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "nvmem.yaml#"
index fa46670..230d74f 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 MIPI D-PHY Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#phy-cells":
index cd0503b..bfefd09 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Pin Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#gpio-cells":
index 0ac52f8..4a21fe7 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 PWM Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#pwm-cells":
index acf18d1..c0d8386 100644 (file)
@@ -50,6 +50,8 @@ properties:
     description: Should contain the WWDG1 watchdog reset interrupt
     maxItems: 1
 
+  wakeup-source: true
+
   mboxes:
     description:
       This property is required only if the rpmsg/virtio functionality is used.
index 6e5341b..ee59409 100644 (file)
@@ -22,6 +22,6 @@ Example:
        };
 
        &ethernet_switch {
-               resets = <&reset>;
+               resets = <&reset 26>;
                reset-names = "switch";
        };
index 46d69c3..478b023 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index d7a57ec..37c2a60 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 RTC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#clock-cells":
index ee9712f..2ecab8e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 PS2 Host Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 description:
   A20 PS2 is dual role controller (PS2 host and PS2 device). These
index b8f89c7..ea1d2ef 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index eb39921..112ae00 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 I2S Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index 38d4ced..444a432 100644 (file)
@@ -10,7 +10,7 @@ maintainers:
   - Chen-Yu Tsai <wens@csie.org>
   - Liam Girdwood <lgirdwood@gmail.com>
   - Mark Brown <broonie@kernel.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index f290eb7..3b76441 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 Analog Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 85305b4..9718358 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A23 Analog Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 5e7cc05..55d2826 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A33 Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index 6d1329c..8036499 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index f36c46d..0565dc4 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index 20adc1c..23e989e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Timer Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index dfa0c41..40fc4bc 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A13 High-Speed Timer Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 0af70fc..d9207bf 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 mUSB OTG Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 3a54f58..e8f2263 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index b0c0853..db6d39c 100644 (file)
@@ -24,11 +24,11 @@ Here is the main features of EROFS:
  - Metadata & data could be mixed by design;
 
  - 2 inode versions for different requirements:
-                          v1            v2
+                          compact (v1)  extended (v2)
    Inode metadata size:   32 bytes      64 bytes
    Max file size:         4 GB          16 EB (also limited by max. vol size)
    Max uids/gids:         65536         4294967296
-   File creation time:    no            yes (64 + 32-bit timestamp)
+   File change time:      no            yes (64 + 32-bit timestamp)
    Max hardlinks:         65536         4294967296
    Metadata reserved:     4 bytes       14 bytes
 
@@ -39,7 +39,7 @@ Here is the main features of EROFS:
  - Support POSIX.1e ACLs by using xattrs;
 
  - Support transparent file compression as an option:
-   LZ4 algorithm with 4 KB fixed-output compression for high performance;
+   LZ4 algorithm with 4 KB fixed-sized output compression for high performance.
 
 The following git tree provides the file system user-space tools under
 development (ex, formatting tool mkfs.erofs):
@@ -85,7 +85,7 @@ All data areas should be aligned with the block size, but metadata areas
 may not. All metadatas can be now observed in two different spaces (views):
  1. Inode metadata space
     Each valid inode should be aligned with an inode slot, which is a fixed
-    value (32 bytes) and designed to be kept in line with v1 inode size.
+    value (32 bytes) and designed to be kept in line with compact inode size.
 
     Each inode can be directly found with the following formula:
          inode offset = meta_blkaddr * block_size + 32 * nid
@@ -117,10 +117,10 @@ may not. All metadatas can be now observed in two different spaces (views):
                                                        |-> aligned with 4B
 
     Inode could be 32 or 64 bytes, which can be distinguished from a common
-    field which all inode versions have -- i_advise:
+    field which all inode versions have -- i_format:
 
         __________________               __________________
-       |     i_advise     |             |     i_advise     |
+       |     i_format     |             |     i_format     |
        |__________________|             |__________________|
        |        ...       |             |        ...       |
        |                  |             |                  |
@@ -129,12 +129,13 @@ may not. All metadatas can be now observed in two different spaces (views):
                                         |__________________| 64 bytes
 
     Xattrs, extents, data inline are followed by the corresponding inode with
-    proper alignes, and they could be optional for different data mappings,
-    _currently_ there are totally 3 valid data mappings supported:
+    proper alignment, and they could be optional for different data mappings.
+    _currently_ total 4 valid data mappings are supported:
 
-     1) flat file data without data inline (no extent);
-     2) fixed-output size data compression (must have extents);
-     3) flat file data with tail-end data inline (no extent);
+     0  flat file data without data inline (no extent);
+     1  fixed-sized output data compression (with non-compacted indexes);
+     2  flat file data with tail packing data inline (no extent);
+     3  fixed-sized output data compression (with compacted indexes, v5.3+).
 
     The size of the optional xattrs is indicated by i_xattr_count in inode
     header. Large xattrs or xattrs shared by many different files can be
@@ -182,8 +183,8 @@ introduce another on-disk field at all.
 
 Compression
 -----------
-Currently, EROFS supports 4KB fixed-output clustersize transparent file
-compression, as illustrated below:
+Currently, EROFS supports 4KB fixed-sized output transparent file compression,
+as illustrated below:
 
          |---- Variant-Length Extent ----|-------- VLE --------|----- VLE -----
          clusterofs                      clusterofs            clusterofs
similarity index 99%
rename from Documentation/filesystems/overlayfs.txt
rename to Documentation/filesystems/overlayfs.rst
index 845d689..e443be7 100644 (file)
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 Written by: Neil Brown
 Please see MAINTAINERS file for where to send questions.
 
@@ -181,7 +183,7 @@ Kernel config options:
     worried about backward compatibility with kernels that have the redirect_dir
     feature and follow redirects even if turned off.
 
-Module options (can also be changed through /sys/module/overlay/parameters/*):
+Module options (can also be changed through /sys/module/overlay/parameters/):
 
 - "redirect_dir=BOOL":
     See OVERLAY_FS_REDIRECT_DIR kernel config option above.
@@ -263,7 +265,7 @@ top, lower2 the middle and lower3 the bottom layer.
 
 
 Metadata only copy up
---------------------
+---------------------
 
 When metadata only copy up feature is enabled, overlayfs will only copy
 up metadata (as opposed to whole file), when a metadata specific operation
@@ -286,10 +288,10 @@ pointed by REDIRECT. This should not be possible on local system as setting
 "trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible
 for untrusted layers like from a pen drive.
 
-Note: redirect_dir={off|nofollow|follow(*)} conflicts with metacopy=on, and
+Note: redirect_dir={off|nofollow|follow[*]} conflicts with metacopy=on, and
 results in an error.
 
-(*) redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
+[*] redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
 given.
 
 Sharing and copying layers
index ada573b..edb296c 100644 (file)
@@ -988,7 +988,7 @@ Similarly, if you need to calculate the size of some structure member, use
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 There are also min() and max() macros that do strict type checking if you
 need them.  Feel free to peruse that header file to see what else is already
index 201f80c..df129f5 100644 (file)
@@ -29,7 +29,7 @@ smartpqi specific entries in /sys
   smartpqi host attributes:
   -------------------------
   /sys/class/scsi_host/host*/rescan
-  /sys/class/scsi_host/host*/version
+  /sys/class/scsi_host/host*/driver_version
 
   The host rescan attribute is a write only attribute. Writing to this
   attribute will trigger the driver to scan for new, changed, or removed
index 8995d2d..8725f2b 100644 (file)
@@ -1005,7 +1005,7 @@ struttura, usate
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 Ci sono anche le macro min() e max() che, se vi serve, effettuano un controllo
 rigido sui tipi.  Sentitevi liberi di leggere attentamente questo file
index 4f62373..eae10bc 100644 (file)
@@ -826,7 +826,7 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以
 自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应
index bd5847e..a049abc 100644 (file)
@@ -2272,6 +2272,7 @@ F:        drivers/*/*s3c64xx*
 F:     drivers/*/*s5pv210*
 F:     drivers/memory/samsung/
 F:     drivers/soc/samsung/
+F:     drivers/tty/serial/samsung*
 F:     include/linux/soc/samsung/
 F:     Documentation/arm/samsung/
 F:     Documentation/devicetree/bindings/arm/samsung/
@@ -4970,6 +4971,7 @@ F:        include/linux/dma-buf*
 F:     include/linux/reservation.h
 F:     include/linux/*fence.h
 F:     Documentation/driver-api/dma-buf.rst
+K:     dma_(buf|fence|resv)
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
@@ -4999,7 +5001,7 @@ F:        include/linux/dma-mapping.h
 F:     include/linux/dma-noncoherent.h
 
 DMC FREQUENCY DRIVER FOR SAMSUNG EXYNOS5422
-M:     Lukasz Luba <l.luba@partner.samsung.com>
+M:     Lukasz Luba <lukasz.luba@arm.com>
 L:     linux-pm@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
 S:     Maintained
@@ -12393,7 +12395,7 @@ L:      linux-unionfs@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
 S:     Supported
 F:     fs/overlayfs/
-F:     Documentation/filesystems/overlayfs.txt
+F:     Documentation/filesystems/overlayfs.rst
 
 P54 WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
@@ -16314,12 +16316,10 @@ F:    drivers/media/radio/radio-raremono.c
 
 THERMAL
 M:     Zhang Rui <rui.zhang@intel.com>
-M:     Eduardo Valentin <edubezval@gmail.com>
-R:     Daniel Lezcano <daniel.lezcano@linaro.org>
+M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 R:     Amit Kucheria <amit.kucheria@verdurent.com>
 L:     linux-pm@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git
 Q:     https://patchwork.kernel.org/project/linux-pm/list/
 S:     Supported
 F:     drivers/thermal/
index 01072d0..e51b53c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
index dc05a63..27ea64b 100644 (file)
@@ -42,10 +42,10 @@ do {                                                \
 
 #define EXTRA_INFO(f) { \
                BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
-                               % FIELD_SIZEOF(struct unwind_frame_info, f)) \
+                               % sizeof_field(struct unwind_frame_info, f)) \
                                + offsetof(struct unwind_frame_info, f) \
-                               / FIELD_SIZEOF(struct unwind_frame_info, f), \
-                               FIELD_SIZEOF(struct unwind_frame_info, f) \
+                               / sizeof_field(struct unwind_frame_info, f), \
+                               sizeof_field(struct unwind_frame_info, f) \
        }
 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
 
index 8678e6e..e5fdb7a 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
 };
 
 &i2c0 {
index cae4500..811c8ca 100644 (file)
@@ -86,7 +86,7 @@
                };
 
        lcd0: display {
-               compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+               compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
                label = "lcd";
 
                backlight = <&lcd_bl>;
index 9531412..078cb47 100644 (file)
@@ -42,7 +42,7 @@
        };
 
        lcd0: display {
-               compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+               compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
                label = "lcd";
 
                backlight = <&lcd_bl>;
index 2dac3ef..1bc45cf 100644 (file)
                mdio: mdio@18002000 {
                        compatible = "brcm,iproc-mdio";
                        reg = <0x18002000 0x8>;
-                       #size-cells = <1>;
-                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       #address-cells = <1>;
                        status = "disabled";
 
                        gphy0: ethernet-phy@0 {
index 961bed8..e2f6ffb 100644 (file)
@@ -43,7 +43,7 @@
                         <0x7c000000  0x0 0xfc000000  0x02000000>,
                         <0x40000000  0x0 0xff800000  0x00800000>;
                /* Emulate a contiguous 30-bit address range for DMA */
-               dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
+               dma-ranges = <0xc0000000  0x0 0x00000000  0x40000000>;
 
                /*
                 * This node is the provider for the enable-method for
index 3caaa57..8394916 100644 (file)
@@ -37,7 +37,7 @@
 
                        trips {
                                cpu-crit {
-                                       temperature     = <80000>;
+                                       temperature     = <90000>;
                                        hysteresis      = <0>;
                                        type            = "critical";
                                };
index 372dc1e..2d9b4dd 100644 (file)
        mdio: mdio@18003000 {
                compatible = "brcm,iproc-mdio";
                reg = <0x18003000 0x8>;
-               #size-cells = <1>;
-               #address-cells = <0>;
+               #size-cells = <0>;
+               #address-cells = <1>;
        };
 
        mdio-bus-mux@18003000 {
index 6472b05..5a2c532 100644 (file)
                                regulator-name = "LDORTC1";
                                regulator-boot-on;
                        };
-
-                       ldortc2_reg: LDORTC2 {
-                               regulator-name = "LDORTC2";
-                               regulator-boot-on;
-                       };
                };
        };
 };
index 1506eb1..2121445 100644 (file)
                enable-active-high;
        };
 
-       reg_sensors: regulator-sensors {
+       reg_peri_3v3: regulator-peri-3v3 {
                compatible = "regulator-fixed";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_sensors_reg>;
-               regulator-name = "sensors-supply";
+               pinctrl-0 = <&pinctrl_peri_3v3>;
+               regulator-name = "VPERI_3V3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                gpio = <&gpio5 2 GPIO_ACTIVE_LOW>;
+               /*
+                * If you want to want to make this dynamic please
+                * check schematics and test all affected peripherals:
+                *
+                * - sensors
+                * - ethernet phy
+                * - can
+                * - bluetooth
+                * - wm8960 audio codec
+                * - ov5640 camera
+                */
+               regulator-always-on;
        };
 
        reg_can_3v3: regulator-can-3v3 {
        pinctrl-0 = <&pinctrl_enet1>;
        phy-mode = "rmii";
        phy-handle = <&ethphy0>;
+       phy-supply = <&reg_peri_3v3>;
        status = "okay";
 };
 
        pinctrl-0 = <&pinctrl_enet2>;
        phy-mode = "rmii";
        phy-handle = <&ethphy1>;
+       phy-supply = <&reg_peri_3v3>;
        status = "okay";
 
        mdio {
        magnetometer@e {
                compatible = "fsl,mag3110";
                reg = <0x0e>;
-               vdd-supply = <&reg_sensors>;
-               vddio-supply = <&reg_sensors>;
+               vdd-supply = <&reg_peri_3v3>;
+               vddio-supply = <&reg_peri_3v3>;
        };
 };
 
        flash0: n25q256a@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "micron,n25q256a";
+               compatible = "micron,n25q256a", "jedec,spi-nor";
                spi-max-frequency = <29000000>;
                spi-rx-bus-width = <4>;
                spi-tx-bus-width = <4>;
                >;
        };
 
-       pinctrl_sensors_reg: sensorsreggrp {
+       pinctrl_peri_3v3: peri3v3grp {
                fsl,pins = <
                        MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02      0x1b0b0
                >;
index e7e4bb5..fde84f1 100644 (file)
@@ -350,6 +350,7 @@ CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_SOFTLOCKUP_DETECTOR=y
 # CONFIG_DETECT_HUNG_TASK is not set
index 26d6dee..3608e55 100644 (file)
@@ -462,6 +462,7 @@ CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
index 8c37cc8..c32c338 100644 (file)
@@ -92,6 +92,7 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETFILTER=y
 CONFIG_PHONET=m
+CONFIG_NET_SWITCHDEV=y
 CONFIG_CAN=m
 CONFIG_CAN_C_CAN=m
 CONFIG_CAN_C_CAN_PLATFORM=m
@@ -181,6 +182,7 @@ CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_TI_DAVINCI_EMAC=y
 CONFIG_TI_CPSW=y
+CONFIG_TI_CPSW_SWITCHDEV=y
 CONFIG_TI_CPTS=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
@@ -554,6 +556,6 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_SPLIT=y
 CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_TI_CPSW_SWITCHDEV=y
index bda57ca..de38304 100644 (file)
@@ -212,4 +212,5 @@ CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
index f3f42cf..776ae07 100644 (file)
@@ -38,6 +38,13 @@ void curve25519_arch(u8 out[CURVE25519_KEY_SIZE],
 }
 EXPORT_SYMBOL(curve25519_arch);
 
+void curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE],
+                         const u8 secret[CURVE25519_KEY_SIZE])
+{
+       return curve25519_arch(pub, secret, curve25519_base_point);
+}
+EXPORT_SYMBOL(curve25519_base_arch);
+
 static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
                                 unsigned int len)
 {
index dbe2967..fa0300d 100644 (file)
@@ -13,6 +13,7 @@ static const char * const bcm2711_compat[] = {
 #ifdef CONFIG_ARCH_MULTI_V7
        "brcm,bcm2711",
 #endif
+       NULL
 };
 
 DT_MACHINE_START(BCM2711, "BCM2711")
index d811803..871f983 100644 (file)
@@ -84,7 +84,7 @@ struct device * __init imx_soc_device_init(void)
        const char *ocotp_compat = NULL;
        struct soc_device *soc_dev;
        struct device_node *root;
-       struct regmap *ocotp;
+       struct regmap *ocotp = NULL;
        const char *soc_id;
        u64 soc_uid = 0;
        u32 val;
@@ -148,11 +148,11 @@ struct device * __init imx_soc_device_init(void)
                soc_id = "i.MX6UL";
                break;
        case MXC_CPU_IMX6ULL:
-               ocotp_compat = "fsl,imx6ul-ocotp";
+               ocotp_compat = "fsl,imx6ull-ocotp";
                soc_id = "i.MX6ULL";
                break;
        case MXC_CPU_IMX6ULZ:
-               ocotp_compat = "fsl,imx6ul-ocotp";
+               ocotp_compat = "fsl,imx6ull-ocotp";
                soc_id = "i.MX6ULZ";
                break;
        case MXC_CPU_IMX6SLL:
@@ -175,7 +175,9 @@ struct device * __init imx_soc_device_init(void)
                ocotp = syscon_regmap_lookup_by_compatible(ocotp_compat);
                if (IS_ERR(ocotp))
                        pr_err("%s: failed to find %s regmap!\n", __func__, ocotp_compat);
+       }
 
+       if (!IS_ERR_OR_NULL(ocotp)) {
                regmap_read(ocotp, OCOTP_UID_H, &val);
                soc_uid = val;
                regmap_read(ocotp, OCOTP_UID_L, &val);
index 0331c58..dff651b 100644 (file)
@@ -17,9 +17,9 @@ extern void pxa168_clear_keypad_wakeup(void);
 #include <linux/platform_data/keypad-pxa27x.h>
 #include <linux/pxa168_eth.h>
 #include <linux/platform_data/mv_usb.h>
+#include <linux/soc/mmp/cputype.h>
 
 #include "devices.h"
-#include "cputype.h"
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
index 354e0e7..1da11bd 100644 (file)
@@ -551,8 +551,9 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
 
 static int __init ve_spc_clk_init(void)
 {
-       int cpu;
+       int cpu, cluster;
        struct clk *clk;
+       bool init_opp_table[MAX_CLUSTERS] = { false };
 
        if (!info)
                return 0; /* Continue only if SPC is initialised */
@@ -578,8 +579,17 @@ static int __init ve_spc_clk_init(void)
                        continue;
                }
 
+               cluster = topology_physical_package_id(cpu_dev->id);
+               if (init_opp_table[cluster])
+                       continue;
+
                if (ve_init_opp_table(cpu_dev))
                        pr_warn("failed to initialise cpu%d opp table\n", cpu);
+               else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
+                        topology_core_cpumask(cpu_dev->id)))
+                       pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
+               else
+                       init_opp_table[cluster] = true;
        }
 
        platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
index 8e8a77e..13a3cbe 100644 (file)
@@ -88,7 +88,7 @@
 
        reboot {
                compatible ="syscon-reboot";
-               regmap = <&dcfg>;
+               regmap = <&rst>;
                offset = <0xb0>;
                mask = <0x02>;
        };
                        big-endian;
                };
 
+               rst: syscon@1e60000 {
+                       compatible = "syscon";
+                       reg = <0x0 0x1e60000 0x0 0x10000>;
+                       little-endian;
+               };
+
                scfg: syscon@1fc0000 {
                        compatible = "fsl,ls1028a-scfg", "syscon";
                        reg = <0x0 0x1fc0000 0x0 0x10000>;
                                               0x00010004 0x0000003d
                                               0x00010005 0x00000045
                                               0x00010006 0x0000004d
-                                              0x00010007 0x00000045
+                                              0x00010007 0x00000055
                                               0x00010008 0x0000005e
                                               0x00010009 0x00000066
                                               0x0001000a 0x0000006e
index 6a09ca7..85f4bec 100644 (file)
@@ -547,6 +547,7 @@ static const struct midr_range spectre_v2_safe_list[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
        MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
+       MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
        { /* sentinel */ }
 };
 
index ba8f82a..e794b2d 100644 (file)
@@ -45,13 +45,6 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
 /* See header file for descriptions of functions */
 
 /**
- * This macro returns the size of a member of a structure.
- * Logically it is the same as "sizeof(s::field)" in C++, but
- * C lacks the "::" operator.
- */
-#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field)
-
-/**
  * This macro returns a member of the
  * cvmx_bootmem_named_block_desc_t structure. These members can't
  * be directly addressed as they might be in memory not directly
@@ -65,7 +58,7 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
 #define CVMX_BOOTMEM_NAMED_GET_FIELD(addr, field)                      \
        __cvmx_bootmem_desc_get(addr,                                   \
                offsetof(struct cvmx_bootmem_named_block_desc, field),  \
-               SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
+               sizeof_field(struct cvmx_bootmem_named_block_desc, field))
 
 /**
  * This function is the implementation of the get macros defined
index b56af75..819bdfc 100644 (file)
@@ -138,6 +138,14 @@ void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
                                return NULL;
        }
 
+       /*
+        * Map uncached objects in the low part of address space to
+        * CONFIG_NIOS2_IO_REGION_BASE
+        */
+       if (IS_MAPPABLE_UNCACHEABLE(phys_addr) &&
+           IS_MAPPABLE_UNCACHEABLE(last_addr))
+               return (void __iomem *)(CONFIG_NIOS2_IO_REGION_BASE + phys_addr);
+
        /* Mappings have to be page-aligned */
        offset = phys_addr & ~PAGE_MASK;
        phys_addr &= PAGE_MASK;
index f627c37..ab5c215 100644 (file)
@@ -44,8 +44,14 @@ __xchg(unsigned long x, __volatile__ void *ptr, int size)
 **             if (((unsigned long)p & 0xf) == 0)
 **                     return __ldcw(p);
 */
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+#define xchg(ptr, x)                                                   \
+({                                                                     \
+       __typeof__(*(ptr)) __ret;                                       \
+       __typeof__(*(ptr)) _x_ = (x);                                   \
+       __ret = (__typeof__(*(ptr)))                                    \
+               __xchg((unsigned long)_x_, (ptr), sizeof(*(ptr)));      \
+       __ret;                                                          \
+})
 
 /* bug catcher for when unsupported size is used - won't link */
 extern void __cmpxchg_called_with_bad_pointer(void);
index a99ea74..87e1740 100644 (file)
@@ -2,8 +2,6 @@
 #ifndef _ASM_PARISC_KEXEC_H
 #define _ASM_PARISC_KEXEC_H
 
-#ifdef CONFIG_KEXEC
-
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
 /* Maximum address we can reach in physical address mode */
@@ -32,6 +30,4 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_KEXEC */
-
 #endif /* _ASM_PARISC_KEXEC_H */
index 2663c8f..068d909 100644 (file)
@@ -37,5 +37,5 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER)   += ftrace.o
 obj-$(CONFIG_JUMP_LABEL)               += jump_label.o
 obj-$(CONFIG_KGDB)                     += kgdb.o
 obj-$(CONFIG_KPROBES)                  += kprobes.o
-obj-$(CONFIG_KEXEC)                    += kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)               += kexec.o relocate_kernel.o
 obj-$(CONFIG_KEXEC_FILE)               += kexec_file.o
index 3b330e5..a6c9f49 100644 (file)
@@ -810,7 +810,7 @@ EXPORT_SYMBOL(device_to_hwpath);
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
                             struct device *parent);
 
-static void walk_lower_bus(struct parisc_device *dev)
+static void __init walk_lower_bus(struct parisc_device *dev)
 {
        unsigned long io_io_low, io_io_high;
 
index 36434d4..749c457 100644 (file)
@@ -327,8 +327,7 @@ static int pdt_mainloop(void *unused)
                            ((pde & PDT_ADDR_SINGLE_ERR) == 0))
                                memory_failure(pde >> PAGE_SHIFT, 0);
                        else
-                               soft_offline_page(
-                                       pfn_to_page(pde >> PAGE_SHIFT), 0);
+                               soft_offline_page(pde >> PAGE_SHIFT, 0);
 #else
                        pr_crit("PDT: memory error at 0x%lx ignored.\n"
                                "Rebuild kernel with CONFIG_MEMORY_FAILURE=y "
index e9a960e..1b55fc0 100644 (file)
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
+DECLARE_STATIC_KEY_FALSE(shared_processor);
+
 #define vcpu_is_preempted vcpu_is_preempted
 static inline bool vcpu_is_preempted(int cpu)
 {
-       if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+       if (!static_branch_unlikely(&shared_processor))
                return false;
        return !!(be32_to_cpu(lppaca_of(cpu).yield_count) & 1);
 }
@@ -110,13 +112,8 @@ static inline void splpar_rw_yield(arch_rwlock_t *lock) {};
 
 static inline bool is_shared_processor(void)
 {
-/*
- * LPPACA is only available on Pseries so guard anything LPPACA related to
- * allow other platforms (which include this common header) to compile.
- */
-#ifdef CONFIG_PPC_PSERIES
-       return (IS_ENABLED(CONFIG_PPC_SPLPAR) &&
-               lppaca_shared_proc(local_paca->lppaca_ptr));
+#ifdef CONFIG_PPC_SPLPAR
+       return static_branch_unlikely(&shared_processor);
 #else
        return false;
 #endif
index 15002b5..c92fe7f 100644 (file)
@@ -401,7 +401,7 @@ copy_to_user_mcsafe(void __user *to, const void *from, unsigned long n)
        return n;
 }
 
-extern unsigned long __clear_user(void __user *addr, unsigned long size);
+unsigned long __arch_clear_user(void __user *addr, unsigned long size);
 
 static inline unsigned long clear_user(void __user *addr, unsigned long size)
 {
@@ -409,12 +409,17 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size)
        might_fault();
        if (likely(access_ok(addr, size))) {
                allow_write_to_user(addr, size);
-               ret = __clear_user(addr, size);
+               ret = __arch_clear_user(addr, size);
                prevent_write_to_user(addr, size);
        }
        return ret;
 }
 
+static inline unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+       return clear_user(addr, size);
+}
+
 extern long strncpy_from_user(char *dst, const char __user *src, long count);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
index 5645bc9..add6749 100644 (file)
@@ -619,8 +619,6 @@ void __do_irq(struct pt_regs *regs)
 
        trace_irq_entry(regs);
 
-       check_stack_overflow();
-
        /*
         * Query the platform PIC for the interrupt & ack it.
         *
@@ -652,6 +650,8 @@ void do_IRQ(struct pt_regs *regs)
        irqsp = hardirq_ctx[raw_smp_processor_id()];
        sirqsp = softirq_ctx[raw_smp_processor_id()];
 
+       check_stack_overflow();
+
        /* Already there ? */
        if (unlikely(cursp == irqsp || cursp == sirqsp)) {
                __do_irq(regs);
index 0496e66..c6fbbd2 100644 (file)
@@ -1117,7 +1117,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        ld      r7, VCPU_GPR(R7)(r4)
        bne     ret_to_ultra
 
-       lwz     r0, VCPU_CR(r4)
+       l     r0, VCPU_CR(r4)
        mtcr    r0
 
        ld      r0, VCPU_GPR(R0)(r4)
@@ -1137,7 +1137,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
  *   R3 = UV_RETURN
  */
 ret_to_ultra:
-       lwz     r0, VCPU_CR(r4)
+       l     r0, VCPU_CR(r4)
        mtcr    r0
 
        ld      r0, VCPU_GPR(R3)(r4)
index f69a6aa..1ddb263 100644 (file)
@@ -17,7 +17,7 @@ CACHELINE_BYTES = L1_CACHE_BYTES
 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
 CACHELINE_MASK = (L1_CACHE_BYTES-1)
 
-_GLOBAL(__clear_user)
+_GLOBAL(__arch_clear_user)
 /*
  * Use dcbz on the complete cache lines in the destination
  * to set them to zero.  This requires that the destination
@@ -87,4 +87,4 @@ _GLOBAL(__clear_user)
        EX_TABLE(8b, 91b)
        EX_TABLE(9b, 91b)
 
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
index 507b18b..169872b 100644 (file)
@@ -17,7 +17,7 @@ PPC64_CACHES:
        .section        ".text"
 
 /**
- * __clear_user: - Zero a block of memory in user space, with less checking.
+ * __arch_clear_user: - Zero a block of memory in user space, with less checking.
  * @to:   Destination address, in user space.
  * @n:    Number of bytes to zero.
  *
@@ -58,7 +58,7 @@ err3; stb     r0,0(r3)
        mr      r3,r4
        blr
 
-_GLOBAL_TOC(__clear_user)
+_GLOBAL_TOC(__arch_clear_user)
        cmpdi   r4,32
        neg     r6,r3
        li      r0,0
@@ -181,4 +181,4 @@ err1;       dcbz    0,r3
        cmpdi   r4,32
        blt     .Lshort_clear
        b       .Lmedium_clear
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
index 9488b63..617c277 100644 (file)
@@ -289,6 +289,14 @@ void __init mem_init(void)
        BUILD_BUG_ON(MMU_PAGE_COUNT > 16);
 
 #ifdef CONFIG_SWIOTLB
+       /*
+        * Some platforms (e.g. 85xx) limit DMA-able memory way below
+        * 4G. We force memblock to bottom-up mode to ensure that the
+        * memory allocated in swiotlb_init() is DMA-able.
+        * As it's the last memblock allocation, no need to reset it
+        * back to to-down.
+        */
+       memblock_set_bottom_up(true);
        swiotlb_init(0);
 #endif
 
index 090af2d..96eb8e4 100644 (file)
@@ -103,7 +103,7 @@ static void mmu_patch_addis(s32 *site, long simm)
        patch_instruction_site(site, instr);
 }
 
-void __init mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
+static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
 {
        unsigned long s = offset;
        unsigned long v = PAGE_OFFSET + s;
index 6e5a2a4..4ec2a9f 100644 (file)
@@ -97,12 +97,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
 #ifdef CONFIG_SMP
 #ifdef CONFIG_PPC64
 #define PPC_BPF_LOAD_CPU(r)            \
-       do { BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct, paca_index) != 2);   \
+       do { BUILD_BUG_ON(sizeof_field(struct paca_struct, paca_index) != 2);   \
                PPC_LHZ_OFFS(r, 13, offsetof(struct paca_struct, paca_index));  \
        } while (0)
 #else
 #define PPC_BPF_LOAD_CPU(r)     \
-       do { BUILD_BUG_ON(FIELD_SIZEOF(struct task_struct, cpu) != 4);          \
+       do { BUILD_BUG_ON(sizeof_field(struct task_struct, cpu) != 4);          \
                PPC_LHZ_OFFS(r, 2, offsetof(struct task_struct, cpu));          \
        } while(0)
 #endif
index d57b46e..0acc9d5 100644 (file)
@@ -321,7 +321,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                        ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
                        break;
                case BPF_LD | BPF_W | BPF_LEN: /*       A = skb->len; */
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, len) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
                        break;
                case BPF_LDX | BPF_W | BPF_ABS: /* A = *((u32 *)(seccomp_data + K)); */
@@ -333,16 +333,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 
                        /*** Ancillary info loads ***/
                case BPF_ANC | SKF_AD_PROTOCOL: /* A = ntohs(skb->protocol); */
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff,
                                                  protocol) != 2);
                        PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                            protocol));
                        break;
                case BPF_ANC | SKF_AD_IFINDEX:
                case BPF_ANC | SKF_AD_HATYPE:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                       BUILD_BUG_ON(sizeof_field(struct net_device,
                                                ifindex) != 4);
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                       BUILD_BUG_ON(sizeof_field(struct net_device,
                                                type) != 2);
                        PPC_LL_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
                                                                dev));
@@ -365,17 +365,17 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 
                        break;
                case BPF_ANC | SKF_AD_MARK:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, mark) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          mark));
                        break;
                case BPF_ANC | SKF_AD_RXHASH:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, hash) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          hash));
                        break;
                case BPF_ANC | SKF_AD_VLAN_TAG:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_tci) != 2);
 
                        PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          vlan_tci));
@@ -388,7 +388,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                                PPC_ANDI(r_A, r_A, 1);
                        break;
                case BPF_ANC | SKF_AD_QUEUE:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff,
                                                  queue_mapping) != 2);
                        PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          queue_mapping));
index 9157184..9dba7e8 100644 (file)
@@ -539,6 +539,16 @@ static int cmm_migratepage(struct balloon_dev_info *b_dev_info,
        /* balloon page list reference */
        get_page(newpage);
 
+       /*
+        * When we migrate a page to a different zone, we have to fixup the
+        * count of both involved zones as we adjusted the managed page count
+        * when inflating.
+        */
+       if (page_zone(page) != page_zone(newpage)) {
+               adjust_managed_page_count(page, 1);
+               adjust_managed_page_count(newpage, -1);
+       }
+
        spin_lock_irqsave(&b_dev_info->pages_lock, flags);
        balloon_page_insert(b_dev_info, newpage);
        balloon_page_delete(page);
index 0a40201..0c8421d 100644 (file)
@@ -74,6 +74,9 @@
 #include "pseries.h"
 #include "../../../../drivers/pci/pci.h"
 
+DEFINE_STATIC_KEY_FALSE(shared_processor);
+EXPORT_SYMBOL_GPL(shared_processor);
+
 int CMO_PrPSP = -1;
 int CMO_SecPSP = -1;
 unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);
@@ -758,6 +761,10 @@ static void __init pSeries_setup_arch(void)
 
        if (firmware_has_feature(FW_FEATURE_LPAR)) {
                vpa_init(boot_cpuid);
+
+               if (lppaca_shared_proc(get_lppaca()))
+                       static_branch_enable(&shared_processor);
+
                ppc_md.power_save = pseries_lpar_idle;
                ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
 #ifdef CONFIG_PCI_IOV
index 634759a..d325b67 100644 (file)
@@ -2,8 +2,8 @@ menu "SoC selection"
 
 config SOC_SIFIVE
        bool "SiFive SoCs"
-       select SERIAL_SIFIVE
-       select SERIAL_SIFIVE_CONSOLE
+       select SERIAL_SIFIVE if TTY
+       select SERIAL_SIFIVE_CONSOLE if TTY
        select CLK_SIFIVE
        select CLK_SIFIVE_FU540_PRCI
        select SIFIVE_PLIC
index a474f98..36db814 100644 (file)
@@ -24,7 +24,7 @@ $(obj)/Image: vmlinux FORCE
 $(obj)/Image.gz: $(obj)/Image FORCE
        $(call if_changed,gzip)
 
-loader.o: $(src)/loader.S $(obj)/Image
+$(obj)/loader.o: $(src)/loader.S $(obj)/Image
 
 $(obj)/loader: $(obj)/loader.o $(obj)/Image $(obj)/loader.lds FORCE
        $(Q)$(LD) -T $(obj)/loader.lds -o $@ $(obj)/loader.o
index d4051e8..bc88841 100644 (file)
@@ -124,6 +124,7 @@ config S390
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_JUMP_LABEL_RELATIVE
        select HAVE_ARCH_KASAN
+       select HAVE_ARCH_KASAN_VMALLOC
        select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_SOFT_DIRTY
index 6dc6c4f..69289e9 100644 (file)
@@ -27,7 +27,6 @@
 #define MACHINE_FLAG_DIAG9C    BIT(3)
 #define MACHINE_FLAG_ESOP      BIT(4)
 #define MACHINE_FLAG_IDTE      BIT(5)
-#define MACHINE_FLAG_DIAG44    BIT(6)
 #define MACHINE_FLAG_EDAT1     BIT(7)
 #define MACHINE_FLAG_EDAT2     BIT(8)
 #define MACHINE_FLAG_TOPOLOGY  BIT(10)
@@ -94,7 +93,6 @@ extern unsigned long __swsusp_reset_dma;
 #define MACHINE_HAS_DIAG9C     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
 #define MACHINE_HAS_ESOP       (S390_lowcore.machine_flags & MACHINE_FLAG_ESOP)
 #define MACHINE_HAS_IDTE       (S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)
-#define MACHINE_HAS_DIAG44     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
 #define MACHINE_HAS_EDAT1      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
 #define MACHINE_HAS_EDAT2      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
index ef3c00b..4093a28 100644 (file)
@@ -86,7 +86,7 @@ static inline int share(unsigned long addr, u16 cmd)
        };
 
        if (!is_prot_virt_guest())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        /*
         * Sharing is page wise, if we encounter addresses that are
         * not page aligned, we assume something went wrong. If
index db32a55..cd241ee 100644 (file)
@@ -204,21 +204,6 @@ static __init void detect_diag9c(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG9C;
 }
 
-static __init void detect_diag44(void)
-{
-       int rc;
-
-       diag_stat_inc(DIAG_STAT_X044);
-       asm volatile(
-               "       diag    0,0,0x44\n"
-               "0:     la      %0,0\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc");
-       if (!rc)
-               S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG44;
-}
-
 static __init void detect_machine_facilities(void)
 {
        if (test_facility(8)) {
@@ -331,7 +316,6 @@ void __init startup_init(void)
        setup_arch_string();
        setup_boot_command_line();
        detect_diag9c();
-       detect_diag44();
        detect_machine_facilities();
        save_vector_registers();
        setup_topology();
index c07fdcd..77d93c5 100644 (file)
@@ -1303,18 +1303,28 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
                 */
                if (flush_all && done)
                        break;
-
-               /* If an event overflow happened, discard samples by
-                * processing any remaining sample-data-blocks.
-                */
-               if (event_overflow)
-                       flush_all = 1;
        }
 
        /* Account sample overflows in the event hardware structure */
        if (sampl_overflow)
                OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) +
                                                 sampl_overflow, 1 + num_sdb);
+
+       /* Perf_event_overflow() and perf_event_account_interrupt() limit
+        * the interrupt rate to an upper limit. Roughly 1000 samples per
+        * task tick.
+        * Hitting this limit results in a large number
+        * of throttled REF_REPORT_THROTTLE entries and the samples
+        * are dropped.
+        * Slightly increase the interval to avoid hitting this limit.
+        */
+       if (event_overflow) {
+               SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
+               debug_sprintf_event(sfdbg, 1, "%s: rate adjustment %ld\n",
+                                   __func__,
+                                   DIV_ROUND_UP(SAMPL_RATE(hwc), 10));
+       }
+
        if (sampl_overflow || event_overflow)
                debug_sprintf_event(sfdbg, 4, "%s: "
                                    "overflows: sample %llu event %llu"
index 2794cad..a08bd25 100644 (file)
@@ -413,14 +413,11 @@ EXPORT_SYMBOL(arch_vcpu_is_preempted);
 
 void smp_yield_cpu(int cpu)
 {
-       if (MACHINE_HAS_DIAG9C) {
-               diag_stat_inc_norecursion(DIAG_STAT_X09C);
-               asm volatile("diag %0,0,0x9c"
-                            : : "d" (pcpu_devices[cpu].address));
-       } else if (MACHINE_HAS_DIAG44 && !smp_cpu_mtid) {
-               diag_stat_inc_norecursion(DIAG_STAT_X044);
-               asm volatile("diag 0,0,0x44");
-       }
+       if (!MACHINE_HAS_DIAG9C)
+               return;
+       diag_stat_inc_norecursion(DIAG_STAT_X09C);
+       asm volatile("diag %0,0,0x9c"
+                    : : "d" (pcpu_devices[cpu].address));
 }
 
 /*
index ce1e4bb..9b2dab5 100644 (file)
@@ -242,7 +242,6 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
 
 void arch_spin_lock_wait(arch_spinlock_t *lp)
 {
-       /* Use classic spinlocks + niai if the steal time is >= 10% */
        if (test_cpu_flag(CIF_DEDICATED_CPU))
                arch_spin_lock_queued(lp);
        else
index bda7ac0..32b7a30 100644 (file)
@@ -238,7 +238,7 @@ static int test_unwind_irq(struct unwindme *u)
 {
        preempt_disable();
        if (register_external_irq(EXT_IRQ_CLK_COMP, unwindme_irq_handler)) {
-               pr_info("Couldn't reqister external interrupt handler");
+               pr_info("Couldn't register external interrupt handler");
                return -1;
        }
        u->task = current;
index 460f255..0634561 100644 (file)
@@ -82,7 +82,8 @@ static pte_t * __init kasan_early_pte_alloc(void)
 enum populate_mode {
        POPULATE_ONE2ONE,
        POPULATE_MAP,
-       POPULATE_ZERO_SHADOW
+       POPULATE_ZERO_SHADOW,
+       POPULATE_SHALLOW
 };
 static void __init kasan_early_vmemmap_populate(unsigned long address,
                                                unsigned long end,
@@ -116,6 +117,12 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        pgd_populate(&init_mm, pg_dir, p4_dir);
                }
 
+               if (IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING) &&
+                   mode == POPULATE_SHALLOW) {
+                       address = (address + P4D_SIZE) & P4D_MASK;
+                       continue;
+               }
+
                p4_dir = p4d_offset(pg_dir, address);
                if (p4d_none(*p4_dir)) {
                        if (mode == POPULATE_ZERO_SHADOW &&
@@ -130,6 +137,12 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        p4d_populate(&init_mm, p4_dir, pu_dir);
                }
 
+               if (!IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING) &&
+                   mode == POPULATE_SHALLOW) {
+                       address = (address + PUD_SIZE) & PUD_MASK;
+                       continue;
+               }
+
                pu_dir = pud_offset(p4_dir, address);
                if (pud_none(*pu_dir)) {
                        if (mode == POPULATE_ZERO_SHADOW &&
@@ -195,6 +208,9 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                                page = kasan_early_shadow_page;
                                pte_val(*pt_dir) = __pa(page) | pgt_prot_zero;
                                break;
+                       case POPULATE_SHALLOW:
+                               /* should never happen */
+                               break;
                        }
                }
                address += PAGE_SIZE;
@@ -313,22 +329,50 @@ void __init kasan_early_init(void)
        init_mm.pgd = early_pg_dir;
        /*
         * Current memory layout:
-        * +- 0 -------------+   +- shadow start -+
-        * | 1:1 ram mapping |  /| 1/8 ram        |
-        * +- end of ram ----+ / +----------------+
-        * | ... gap ...     |/  |      kasan     |
-        * +- shadow start --+   |      zero      |
-        * | 1/8 addr space  |   |      page      |
-        * +- shadow end    -+   |      mapping   |
-        * | ... gap ...     |\  |    (untracked) |
-        * +- modules vaddr -+ \ +----------------+
-        * | 2Gb             |  \|      unmapped  | allocated per module
-        * +-----------------+   +- shadow end ---+
+        * +- 0 -------------+     +- shadow start -+
+        * | 1:1 ram mapping |    /| 1/8 ram        |
+        * |                 |   / |                |
+        * +- end of ram ----+  /  +----------------+
+        * | ... gap ...     | /   |                |
+        * |                 |/    |    kasan       |
+        * +- shadow start --+     |    zero        |
+        * | 1/8 addr space  |     |    page        |
+        * +- shadow end    -+     |    mapping     |
+        * | ... gap ...     |\    |  (untracked)   |
+        * +- vmalloc area  -+ \   |                |
+        * | vmalloc_size    |  \  |                |
+        * +- modules vaddr -+   \ +----------------+
+        * | 2Gb             |    \|      unmapped  | allocated per module
+        * +-----------------+     +- shadow end ---+
+        *
+        * Current memory layout (KASAN_VMALLOC):
+        * +- 0 -------------+     +- shadow start -+
+        * | 1:1 ram mapping |    /| 1/8 ram        |
+        * |                 |   / |                |
+        * +- end of ram ----+  /  +----------------+
+        * | ... gap ...     | /   |    kasan       |
+        * |                 |/    |    zero        |
+        * +- shadow start --+     |    page        |
+        * | 1/8 addr space  |     |    mapping     |
+        * +- shadow end    -+     |  (untracked)   |
+        * | ... gap ...     |\    |                |
+        * +- vmalloc area  -+ \   +- vmalloc area -+
+        * | vmalloc_size    |  \  |shallow populate|
+        * +- modules vaddr -+   \ +- modules area -+
+        * | 2Gb             |    \|shallow populate|
+        * +-----------------+     +- shadow end ---+
         */
        /* populate kasan shadow (for identity mapping and zero page mapping) */
        kasan_early_vmemmap_populate(__sha(0), __sha(memsize), POPULATE_MAP);
        if (IS_ENABLED(CONFIG_MODULES))
                untracked_mem_end = vmax - MODULES_LEN;
+       if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+               untracked_mem_end = vmax - vmalloc_size - MODULES_LEN;
+               /* shallowly populate kasan shadow for vmalloc and modules */
+               kasan_early_vmemmap_populate(__sha(untracked_mem_end),
+                                            __sha(vmax), POPULATE_SHALLOW);
+       }
+       /* populate kasan shadow for untracked memory */
        kasan_early_vmemmap_populate(__sha(max_physmem_end),
                                     __sha(untracked_mem_end),
                                     POPULATE_ZERO_SHADOW);
index f6d1484..f3dc3f2 100644 (file)
@@ -325,9 +325,9 @@ int __init sh_early_platform_driver_probe(char *class_str,
 }
 
 /**
- * sh_early_platform_cleanup - clean up early platform code
+ * early_platform_cleanup - clean up early platform code
  */
-static int __init sh_early_platform_cleanup(void)
+void __init early_platform_cleanup(void)
 {
        struct platform_device *pd, *pd2;
 
@@ -337,11 +337,4 @@ static int __init sh_early_platform_cleanup(void)
                list_del(&pd->dev.devres_head);
                memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
        }
-
-       return 0;
 }
-/*
- * This must happen once after all early devices are probed but before probing
- * real platform devices.
- */
-subsys_initcall(sh_early_platform_cleanup);
index 6d61f8c..0d5f3c9 100644 (file)
@@ -266,6 +266,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
                ptr = &remcomInBuffer[1];
                if (kgdb_hex2long(&ptr, &addr))
                        linux_regs->pc = addr;
+               /* fallthrough */
        case 'D':
        case 'k':
                atomic_set(&kgdb_cpu_doing_single_step, -1);
index 84cc8f7..c8eabb9 100644 (file)
@@ -180,19 +180,19 @@ do {                                                                      \
 
 #define emit_loadptr(BASE, STRUCT, FIELD, DEST)                                \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *));    \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(void *));    \
        *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST);            \
 } while (0)
 
 #define emit_load32(BASE, STRUCT, FIELD, DEST)                         \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32));       \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u32));       \
        *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST);             \
 } while (0)
 
 #define emit_load16(BASE, STRUCT, FIELD, DEST)                         \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16));       \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u16));       \
        *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST);             \
 } while (0)
 
@@ -202,7 +202,7 @@ do {        unsigned int _off = offsetof(STRUCT, FIELD);                    \
 } while (0)
 
 #define emit_load8(BASE, STRUCT, FIELD, DEST)                          \
-do {   BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8));        \
+do {   BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u8));        \
        __emit_load8(BASE, STRUCT, FIELD, DEST);                        \
 } while (0)
 
index 5167bd2..d6cf5c1 100644 (file)
@@ -266,10 +266,10 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
        smca_set_misc_banks_map(bank, cpu);
 
        /* Return early if this bank was already initialized. */
-       if (smca_banks[bank].hwid)
+       if (smca_banks[bank].hwid && smca_banks[bank].hwid->hwid_mcatype != 0)
                return;
 
-       if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
+       if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
                pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
                return;
        }
index 5f42f25..2e2a421 100644 (file)
@@ -819,8 +819,8 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
                if (quirk_no_way_out)
                        quirk_no_way_out(i, m, regs);
 
+               m->bank = i;
                if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
-                       m->bank = i;
                        mce_read_aux(m, i);
                        *msg = tmp;
                        return 1;
index 4cba91e..2f9ec14 100644 (file)
@@ -710,8 +710,12 @@ static struct chipset early_qrk[] __initdata = {
         */
        { PCI_VENDOR_ID_INTEL, 0x0f00,
                PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+       { PCI_VENDOR_ID_INTEL, 0x3e20,
+               PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
        { PCI_VENDOR_ID_INTEL, 0x3ec4,
                PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+       { PCI_VENDOR_ID_INTEL, 0x8a12,
+               PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
        { PCI_VENDOR_ID_BROADCOM, 0x4331,
          PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
        {}
index 319be93..fa31470 100644 (file)
@@ -259,7 +259,7 @@ static void __init setup_xstate_features(void)
                                                   xmm_space);
 
        xstate_offsets[XFEATURE_SSE]    = xstate_sizes[XFEATURE_FP];
-       xstate_sizes[XFEATURE_SSE]      = FIELD_SIZEOF(struct fxregs_state,
+       xstate_sizes[XFEATURE_SSE]      = sizeof_field(struct fxregs_state,
                                                       xmm_space);
 
        for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
index 060a361..024c305 100644 (file)
@@ -1043,20 +1043,6 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
                return;
 
        /*
-        * If the return location is actually pointing directly to
-        * the start of a direct trampoline (if we trace the trampoline
-        * it will still be offset by MCOUNT_INSN_SIZE), then the
-        * return address is actually off by one word, and we
-        * need to adjust for that.
-        */
-       if (ftrace_direct_func_count) {
-               if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) {
-                       self_addr = *parent;
-                       parent++;
-               }
-       }
-
-       /*
         * Protect against fault, even if it shouldn't
         * happen. This tool is too much intrusive to
         * ignore such a protection.
index 7675cf7..f8f0220 100644 (file)
@@ -260,10 +260,6 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
                return;
        }
 
-       /* No need to reserve regions that will never be freed. */
-       if (md.attribute & EFI_MEMORY_RUNTIME)
-               return;
-
        size += addr % EFI_PAGE_SIZE;
        size = round_up(size, EFI_PAGE_SIZE);
        addr = round_down(addr, EFI_PAGE_SIZE);
@@ -293,6 +289,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
        early_memunmap(new, new_size);
 
        efi_memmap_install(new_phys, num_entries);
+       e820__range_update(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
+       e820__update_table(e820_table);
 }
 
 /*
index 9d54aa3..a5d75f6 100644 (file)
@@ -754,10 +754,12 @@ bool __bio_try_merge_page(struct bio *bio, struct page *page,
        if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
                return false;
 
-       if (bio->bi_vcnt > 0 && !bio_full(bio, len)) {
+       if (bio->bi_vcnt > 0) {
                struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 
                if (page_is_mergeable(bv, page, len, off, same_page)) {
+                       if (bio->bi_iter.bi_size > UINT_MAX - len)
+                               return false;
                        bv->bv_len += len;
                        bio->bi_iter.bi_size += len;
                        return true;
index 708dea9..a229b94 100644 (file)
@@ -1062,26 +1062,6 @@ err_unlock:
 }
 
 /**
- * blkcg_drain_queue - drain blkcg part of request_queue
- * @q: request_queue to drain
- *
- * Called from blk_drain_queue().  Responsible for draining blkcg part.
- */
-void blkcg_drain_queue(struct request_queue *q)
-{
-       lockdep_assert_held(&q->queue_lock);
-
-       /*
-        * @q could be exiting and already have destroyed all blkgs as
-        * indicated by NULL root_blkg.  If so, don't confuse policies.
-        */
-       if (!q->root_blkg)
-               return;
-
-       blk_throtl_drain(q);
-}
-
-/**
  * blkcg_exit_queue - exit and release blkcg part of request_queue
  * @q: request_queue being released
  *
index a1e2287..e0a094f 100644 (file)
@@ -1310,7 +1310,7 @@ EXPORT_SYMBOL_GPL(blk_rq_err_bytes);
 
 void blk_account_io_completion(struct request *req, unsigned int bytes)
 {
-       if (blk_do_io_stat(req)) {
+       if (req->part && blk_do_io_stat(req)) {
                const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
 
@@ -1328,7 +1328,8 @@ void blk_account_io_done(struct request *req, u64 now)
         * normal IO on queueing nor completion.  Accounting the
         * containing request is enough.
         */
-       if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
+       if (req->part && blk_do_io_stat(req) &&
+           !(req->rq_flags & RQF_FLUSH_SEQ)) {
                const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
 
@@ -1792,9 +1793,9 @@ int __init blk_dev_init(void)
 {
        BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS));
        BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
-                       FIELD_SIZEOF(struct request, cmd_flags));
+                       sizeof_field(struct request, cmd_flags));
        BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
-                       FIELD_SIZEOF(struct bio, bi_opf));
+                       sizeof_field(struct bio, bi_opf));
 
        /* used for unplugging and affects IO latency/throughput - HIGHPRI */
        kblockd_workqueue = alloc_workqueue("kblockd",
index aded260..9dc53cf 100644 (file)
@@ -436,10 +436,10 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
 
        BUILD_BUG_ON(offsetofend(struct adiantum_request_ctx, u) !=
                     sizeof(struct adiantum_request_ctx));
-       subreq_size = max(FIELD_SIZEOF(struct adiantum_request_ctx,
+       subreq_size = max(sizeof_field(struct adiantum_request_ctx,
                                       u.hash_desc) +
                          crypto_shash_descsize(hash),
-                         FIELD_SIZEOF(struct adiantum_request_ctx,
+                         sizeof_field(struct adiantum_request_ctx,
                                       u.streamcipher_req) +
                          crypto_skcipher_reqsize(streamcipher));
 
index d16d893..378b18b 100644 (file)
@@ -470,6 +470,7 @@ static int tpm_key_encrypt(struct tpm_key *tk,
        if (ret < 0)
                goto error_free_tfm;
 
+       ret = -ENOMEM;
        req = akcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req)
                goto error_free_tfm;
index 364b9df..d7f43d4 100644 (file)
@@ -184,6 +184,7 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
+       ret = -ENOMEM;
        req = akcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req)
                goto error_free_tfm;
index 808f2b3..495a2d1 100644 (file)
@@ -347,7 +347,7 @@ static int essiv_aead_init_tfm(struct crypto_aead *tfm)
        if (IS_ERR(aead))
                return PTR_ERR(aead);
 
-       subreq_size = FIELD_SIZEOF(struct essiv_aead_request_ctx, aead_req) +
+       subreq_size = sizeof_field(struct essiv_aead_request_ctx, aead_req) +
                      crypto_aead_reqsize(aead);
 
        tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) +
index 08bb9f2..5e4a886 100644 (file)
@@ -1314,9 +1314,19 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
  */
 int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
+       /*
+        * Skip devices whose ACPI companions match the device IDs below,
+        * because they require special power management handling incompatible
+        * with the generic ACPI PM domain.
+        */
+       static const struct acpi_device_id special_pm_ids[] = {
+               {"PNP0C0B", }, /* Generic ACPI fan */
+               {"INT3404", }, /* Fan */
+               {}
+       };
        struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (!adev)
+       if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
                return 0;
 
        /*
index e9bc9fc..b2dad43 100644 (file)
@@ -3310,7 +3310,7 @@ static void binder_transaction(struct binder_proc *proc,
                        binder_size_t parent_offset;
                        struct binder_fd_array_object *fda =
                                to_binder_fd_array_object(hdr);
-                       size_t num_valid = (buffer_offset - off_start_offset) *
+                       size_t num_valid = (buffer_offset - off_start_offset) /
                                                sizeof(binder_size_t);
                        struct binder_buffer_object *parent =
                                binder_validate_ptr(target_proc, t->buffer,
@@ -3384,7 +3384,7 @@ static void binder_transaction(struct binder_proc *proc,
                                t->buffer->user_data + sg_buf_offset;
                        sg_buf_offset += ALIGN(bp->length, sizeof(u64));
 
-                       num_valid = (buffer_offset - off_start_offset) *
+                       num_valid = (buffer_offset - off_start_offset) /
                                        sizeof(binder_size_t);
                        ret = binder_fixup_parent(t, thread, bp,
                                                  off_start_offset,
index 30d0523..6cdbf15 100644 (file)
@@ -359,7 +359,7 @@ static int handle_remove(const char *nodename, struct device *dev)
  * If configured, or requested by the commandline, devtmpfs will be
  * auto-mounted after the kernel mounted the root filesystem.
  */
-int devtmpfs_mount(const char *mntdir)
+int devtmpfs_mount(void)
 {
        int err;
 
@@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir)
        if (!thread)
                return 0;
 
-       err = ksys_mount("devtmpfs", mntdir, "devtmpfs", MS_SILENT, NULL);
+       err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
        if (err)
                printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
        else
@@ -394,7 +394,7 @@ static int devtmpfsd(void *p)
        *err = ksys_unshare(CLONE_NEWNS);
        if (*err)
                goto out;
-       *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
+       *err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
        if (*err)
                goto out;
        ksys_chdir("/.."); /* will traverse into overmounted root */
index 7c53254..cf6b6b7 100644 (file)
@@ -1325,10 +1325,14 @@ struct device *platform_find_device_by_driver(struct device *start,
 }
 EXPORT_SYMBOL_GPL(platform_find_device_by_driver);
 
+void __weak __init early_platform_cleanup(void) { }
+
 int __init platform_bus_init(void)
 {
        int error;
 
+       early_platform_cleanup();
+
        error = device_register(&platform_bus);
        if (error) {
                put_device(&platform_bus);
index e8c5c54..4c5d99f 100644 (file)
@@ -171,6 +171,15 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
        blkif->domid = domid;
        atomic_set(&blkif->refcnt, 1);
        init_completion(&blkif->drain_complete);
+
+       /*
+        * Because freeing back to the cache may be deferred, it is not
+        * safe to unload the module (and hence destroy the cache) until
+        * this has completed. To prevent premature unloading, take an
+        * extra module reference here and release only when the object
+        * has been freed back to the cache.
+        */
+       __module_get(THIS_MODULE);
        INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);
 
        return blkif;
@@ -181,6 +190,9 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref,
 {
        int err;
        struct xen_blkif *blkif = ring->blkif;
+       const struct blkif_common_sring *sring_common;
+       RING_IDX rsp_prod, req_prod;
+       unsigned int size;
 
        /* Already connected through? */
        if (ring->irq)
@@ -191,46 +203,62 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref,
        if (err < 0)
                return err;
 
+       sring_common = (struct blkif_common_sring *)ring->blk_ring;
+       rsp_prod = READ_ONCE(sring_common->rsp_prod);
+       req_prod = READ_ONCE(sring_common->req_prod);
+
        switch (blkif->blk_protocol) {
        case BLKIF_PROTOCOL_NATIVE:
        {
-               struct blkif_sring *sring;
-               sring = (struct blkif_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.native, sring,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_sring *sring_native =
+                       (struct blkif_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.native, sring_native,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_native, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_32:
        {
-               struct blkif_x86_32_sring *sring_x86_32;
-               sring_x86_32 = (struct blkif_x86_32_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_32, sring_x86_32,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_32_sring *sring_x86_32 =
+                       (struct blkif_x86_32_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_32, sring_x86_32,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_32, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_64:
        {
-               struct blkif_x86_64_sring *sring_x86_64;
-               sring_x86_64 = (struct blkif_x86_64_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_64, sring_x86_64,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_64_sring *sring_x86_64 =
+                       (struct blkif_x86_64_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_64, sring_x86_64,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_64, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        default:
                BUG();
        }
 
+       err = -EIO;
+       if (req_prod - rsp_prod > size)
+               goto fail;
+
        err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
                                                    xen_blkif_be_int, 0,
                                                    "blkif-backend", ring);
-       if (err < 0) {
-               xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
-               ring->blk_rings.common.sring = NULL;
-               return err;
-       }
+       if (err < 0)
+               goto fail;
        ring->irq = err;
 
        return 0;
+
+fail:
+       xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
+       ring->blk_rings.common.sring = NULL;
+       return err;
 }
 
 static int xen_blkif_disconnect(struct xen_blkif *blkif)
@@ -320,6 +348,7 @@ static void xen_blkif_free(struct xen_blkif *blkif)
 
        /* Make sure everything is drained before shutting down */
        kmem_cache_free(xen_blkif_cachep, blkif);
+       module_put(THIS_MODULE);
 }
 
 int __init xen_blkif_interface_init(void)
@@ -1121,7 +1150,8 @@ static struct xenbus_driver xen_blkbk_driver = {
        .ids  = xen_blkbk_ids,
        .probe = xen_blkbk_probe,
        .remove = xen_blkbk_remove,
-       .otherend_changed = frontend_changed
+       .otherend_changed = frontend_changed,
+       .allow_rebind = true,
 };
 
 int xen_blkif_xenbus_init(void)
index a74d039..c02be06 100644 (file)
@@ -1113,8 +1113,8 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
        if (!VDEV_IS_EXTENDED(info->vdevice)) {
                err = xen_translate_vdev(info->vdevice, &minor, &offset);
                if (err)
-                       return err;             
-               nr_parts = PARTS_PER_DISK;
+                       return err;
+               nr_parts = PARTS_PER_DISK;
        } else {
                minor = BLKIF_MINOR_EXT(info->vdevice);
                nr_parts = PARTS_PER_EXT_DISK;
index 56887c6..f4d1597 100644 (file)
@@ -981,7 +981,8 @@ static int sysc_disable_module(struct device *dev)
                return ret;
        }
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
+       if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_MSTANDBY) ||
+           ddata->cfg.quirks & (SYSC_QUIRK_FORCE_MSTANDBY))
                best_mode = SYSC_IDLE_FORCE;
 
        reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
@@ -1583,6 +1584,10 @@ static int sysc_reset(struct sysc *ddata)
        sysc_val |= sysc_mask;
        sysc_write(ddata, sysc_offset, sysc_val);
 
+       if (ddata->cfg.srst_udelay)
+               usleep_range(ddata->cfg.srst_udelay,
+                            ddata->cfg.srst_udelay * 2);
+
        if (ddata->clk_enable_quirk)
                ddata->clk_enable_quirk(ddata);
 
index 909e0c3..cda1293 100644 (file)
@@ -2175,6 +2175,7 @@ const struct file_operations urandom_fops = {
        .read  = urandom_read,
        .write = random_write,
        .unlocked_ioctl = random_ioctl,
+       .compat_ioctl = compat_ptr_ioctl,
        .fasync = random_fasync,
        .llseek = noop_llseek,
 };
index 2ec47a6..b23b0b9 100644 (file)
@@ -61,6 +61,12 @@ static void tpm_dev_async_work(struct work_struct *work)
 
        mutex_lock(&priv->buffer_mutex);
        priv->command_enqueued = false;
+       ret = tpm_try_get_ops(priv->chip);
+       if (ret) {
+               priv->response_length = ret;
+               goto out;
+       }
+
        ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
                               sizeof(priv->data_buffer));
        tpm_put_ops(priv->chip);
@@ -68,6 +74,7 @@ static void tpm_dev_async_work(struct work_struct *work)
                priv->response_length = ret;
                mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
        }
+out:
        mutex_unlock(&priv->buffer_mutex);
        wake_up_interruptible(&priv->async_wait);
 }
@@ -204,6 +211,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
        if (file->f_flags & O_NONBLOCK) {
                priv->command_enqueued = true;
                queue_work(tpm_dev_wq, &priv->async_work);
+               tpm_put_ops(priv->chip);
                mutex_unlock(&priv->buffer_mutex);
                return size;
        }
index b9e1547..5620747 100644 (file)
@@ -218,7 +218,6 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
 int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
                    struct tpm_digest *digests);
 int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
-void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
                        u32 *value, const char *desc);
 
index fdb4577..13696de 100644 (file)
@@ -362,6 +362,7 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
        tpm_transmit_cmd(chip, &buf, 0, "flushing context");
        tpm_buf_destroy(&buf);
 }
+EXPORT_SYMBOL_GPL(tpm2_flush_context);
 
 struct tpm2_get_cap_out {
        u8 more_data;
index 6640a14..22bf553 100644 (file)
@@ -32,7 +32,7 @@ static const uuid_t ftpm_ta_uuid =
                  0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
 
 /**
- * ftpm_tee_tpm_op_recv - retrieve fTPM response.
+ * ftpm_tee_tpm_op_recv() - retrieve fTPM response.
  * @chip:      the tpm_chip description as specified in driver/char/tpm/tpm.h.
  * @buf:       the buffer to store data.
  * @count:     the number of bytes to read.
@@ -61,7 +61,7 @@ static int ftpm_tee_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 }
 
 /**
- * ftpm_tee_tpm_op_send - send TPM commands through the TEE shared memory.
+ * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory.
  * @chip:      the tpm_chip description as specified in driver/char/tpm/tpm.h
  * @buf:       the buffer to send.
  * @len:       the number of bytes to send.
@@ -208,7 +208,7 @@ static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
 }
 
 /**
- * ftpm_tee_probe - initialize the fTPM
+ * ftpm_tee_probe() - initialize the fTPM
  * @pdev: the platform_device description.
  *
  * Return:
@@ -298,7 +298,7 @@ out_tee_session:
 }
 
 /**
- * ftpm_tee_remove - remove the TPM device
+ * ftpm_tee_remove() - remove the TPM device
  * @pdev: the platform_device description.
  *
  * Return:
@@ -328,6 +328,19 @@ static int ftpm_tee_remove(struct platform_device *pdev)
        return 0;
 }
 
+/**
+ * ftpm_tee_shutdown() - shutdown the TPM device
+ * @pdev: the platform_device description.
+ */
+static void ftpm_tee_shutdown(struct platform_device *pdev)
+{
+       struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
+
+       tee_shm_free(pvt_data->shm);
+       tee_client_close_session(pvt_data->ctx, pvt_data->session);
+       tee_client_close_context(pvt_data->ctx);
+}
+
 static const struct of_device_id of_ftpm_tee_ids[] = {
        { .compatible = "microsoft,ftpm" },
        { }
@@ -341,6 +354,7 @@ static struct platform_driver ftpm_tee_driver = {
        },
        .probe = ftpm_tee_probe,
        .remove = ftpm_tee_remove,
+       .shutdown = ftpm_tee_shutdown,
 };
 
 module_platform_driver(ftpm_tee_driver);
index 8af2cee..bb0343f 100644 (file)
@@ -978,13 +978,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
 
        if (wait_startup(chip, 0) != 0) {
                rc = -ENODEV;
-               goto out_err;
+               goto err_start;
        }
 
        /* Take control of the TPM's interrupt hardware and shut it off */
        rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
        if (rc < 0)
-               goto out_err;
+               goto err_start;
 
        intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
                   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
@@ -993,21 +993,21 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
 
        rc = tpm_chip_start(chip);
        if (rc)
-               goto out_err;
+               goto err_start;
+
        rc = tpm2_probe(chip);
-       tpm_chip_stop(chip);
        if (rc)
-               goto out_err;
+               goto err_probe;
 
        rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
        if (rc < 0)
-               goto out_err;
+               goto err_probe;
 
        priv->manufacturer_id = vendor;
 
        rc = tpm_tis_read8(priv, TPM_RID(0), &rid);
        if (rc < 0)
-               goto out_err;
+               goto err_probe;
 
        dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
                 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
@@ -1016,13 +1016,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
        probe = probe_itpm(chip);
        if (probe < 0) {
                rc = -ENODEV;
-               goto out_err;
+               goto err_probe;
        }
 
        /* Figure out the capabilities */
        rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
        if (rc < 0)
-               goto out_err;
+               goto err_probe;
 
        dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
                intfcaps);
@@ -1056,10 +1056,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                if (tpm_get_timeouts(chip)) {
                        dev_err(dev, "Could not get TPM timeouts and durations\n");
                        rc = -ENODEV;
-                       goto out_err;
+                       goto err_probe;
                }
 
-               tpm_chip_start(chip);
                chip->flags |= TPM_CHIP_FLAG_IRQ;
                if (irq) {
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
@@ -1070,18 +1069,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                } else {
                        tpm_tis_probe_irq(chip, intmask);
                }
-               tpm_chip_stop(chip);
        }
 
+       tpm_chip_stop(chip);
+
        rc = tpm_chip_register(chip);
        if (rc)
-               goto out_err;
-
-       if (chip->ops->clk_enable != NULL)
-               chip->ops->clk_enable(chip, false);
+               goto err_start;
 
        return 0;
-out_err:
+
+err_probe:
+       tpm_chip_stop(chip);
+
+err_start:
        if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
                chip->ops->clk_enable(chip, false);
 
index 0aabe49..a9d4234 100644 (file)
@@ -348,7 +348,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0ac34cd..77fe83a 100644 (file)
@@ -83,7 +83,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0855f3a..086cf0b 100644 (file)
@@ -146,7 +146,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0b03cfa..b71515a 100644 (file)
@@ -275,7 +275,7 @@ static int __init pmc_register_ops(void)
 
        np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
 
-       pmcreg = syscon_node_to_regmap(np);
+       pmcreg = device_node_to_regmap(np);
        if (IS_ERR(pmcreg))
                return PTR_ERR(pmcreg);
 
index 0de1108..ff7e3f7 100644 (file)
@@ -162,7 +162,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 25b156d..a6dee4a 100644 (file)
@@ -136,7 +136,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index b68e200..6a11239 100644 (file)
@@ -3249,6 +3249,34 @@ static inline void clk_debug_unregister(struct clk_core *core)
 }
 #endif
 
+static void clk_core_reparent_orphans_nolock(void)
+{
+       struct clk_core *orphan;
+       struct hlist_node *tmp2;
+
+       /*
+        * walk the list of orphan clocks and reparent any that newly finds a
+        * parent.
+        */
+       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
+               struct clk_core *parent = __clk_init_parent(orphan);
+
+               /*
+                * We need to use __clk_set_parent_before() and _after() to
+                * to properly migrate any prepare/enable count of the orphan
+                * clock. This is important for CLK_IS_CRITICAL clocks, which
+                * are enabled during init but might not have a parent yet.
+                */
+               if (parent) {
+                       /* update the clk tree topology */
+                       __clk_set_parent_before(orphan, parent);
+                       __clk_set_parent_after(orphan, parent, NULL);
+                       __clk_recalc_accuracies(orphan);
+                       __clk_recalc_rates(orphan, 0);
+               }
+       }
+}
+
 /**
  * __clk_core_init - initialize the data structures in a struct clk_core
  * @core:      clk_core being initialized
@@ -3259,8 +3287,6 @@ static inline void clk_debug_unregister(struct clk_core *core)
 static int __clk_core_init(struct clk_core *core)
 {
        int ret;
-       struct clk_core *orphan;
-       struct hlist_node *tmp2;
        unsigned long rate;
 
        if (!core)
@@ -3407,27 +3433,8 @@ static int __clk_core_init(struct clk_core *core)
                clk_enable_unlock(flags);
        }
 
-       /*
-        * walk the list of orphan clocks and reparent any that newly finds a
-        * parent.
-        */
-       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
-               struct clk_core *parent = __clk_init_parent(orphan);
+       clk_core_reparent_orphans_nolock();
 
-               /*
-                * We need to use __clk_set_parent_before() and _after() to
-                * to properly migrate any prepare/enable count of the orphan
-                * clock. This is important for CLK_IS_CRITICAL clocks, which
-                * are enabled during init but might not have a parent yet.
-                */
-               if (parent) {
-                       /* update the clk tree topology */
-                       __clk_set_parent_before(orphan, parent);
-                       __clk_set_parent_after(orphan, parent, NULL);
-                       __clk_recalc_accuracies(orphan);
-                       __clk_recalc_rates(orphan, 0);
-               }
-       }
 
        kref_init(&core->ref);
 out:
@@ -4179,6 +4186,13 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
 #ifdef CONFIG_OF
+static void clk_core_reparent_orphans(void)
+{
+       clk_prepare_lock();
+       clk_core_reparent_orphans_nolock();
+       clk_prepare_unlock();
+}
+
 /**
  * struct of_clk_provider - Clock provider registration structure
  * @link: Entry in global list of clock providers
@@ -4274,6 +4288,8 @@ int of_clk_add_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clock from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);
@@ -4309,6 +4325,8 @@ int of_clk_add_hw_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clk_hw provider from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);
index 388bdb9..d3486ee 100644 (file)
@@ -142,6 +142,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
        mux->reg = reg;
        mux->shift = PCG_PCS_SHIFT;
        mux->mask = PCG_PCS_MASK;
+       mux->lock = &imx_ccm_lock;
 
        div = kzalloc(sizeof(*div), GFP_KERNEL);
        if (!div)
@@ -161,6 +162,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
        gate_hw = &gate->hw;
        gate->reg = reg;
        gate->bit_idx = PCG_CGC_SHIFT;
+       gate->lock = &imx_ccm_lock;
 
        hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
                        mux_hw, &clk_mux_ops, div_hw,
index 3fdf3d4..281191b 100644 (file)
@@ -40,6 +40,7 @@ static const struct clk_div_table ulp_div_table[] = {
        { .val = 5, .div = 16, },
        { .val = 6, .div = 32, },
        { .val = 7, .div = 64, },
+       { /* sentinel */ },
 };
 
 static const int pcc2_uart_clk_ids[] __initconst = {
index 5c45819..3636c80 100644 (file)
@@ -159,7 +159,7 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
 {
        u32 val;
 
-       return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
+       return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0,
                        LOCK_TIMEOUT_US);
 }
 
index 38424e6..7f59fb8 100644 (file)
@@ -2186,7 +2186,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
        .pd = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
        },
-       .pwrsts = PWRSTS_OFF_ON | VOTABLE,
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
@@ -2194,7 +2195,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
        .pd = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc",
        },
-       .pwrsts = PWRSTS_OFF_ON | VOTABLE,
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc *gcc_sc7180_gdscs[] = {
index e5e2492..9b3923a 100644 (file)
@@ -242,10 +242,12 @@ static struct clk_branch gfx3d_isense_clk = {
 
 static struct gdsc gpu_cx_gdsc = {
        .gdscr = 0x1004,
+       .gds_hw_ctrl = 0x1008,
        .pd = {
                .name = "gpu_cx",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc gpu_gx_gdsc = {
index 506e3f2..83c85d3 100644 (file)
@@ -434,7 +434,7 @@ static int ve_spc_cpufreq_init(struct cpufreq_policy *policy)
        if (cur_cluster < MAX_CLUSTERS) {
                int cpu;
 
-               cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+               dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus);
 
                for_each_cpu(cpu, policy->cpus)
                        per_cpu(physical_cluster, cpu) = cur_cluster;
index 0005be5..33d19c8 100644 (file)
@@ -381,7 +381,8 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv,
                if (dev->states_usage[i].disable)
                        continue;
 
-               limit_ns = (u64)drv->states[i].target_residency_ns;
+               limit_ns = drv->states[i].target_residency_ns;
+               break;
        }
 
        dev->poll_limit_ns = limit_ns;
index c76423a..ce6a5f8 100644 (file)
@@ -403,6 +403,13 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
 
        mutex_lock(&cpuidle_lock);
 
+       spin_lock(&cpuidle_driver_lock);
+
+       if (!drv->cpumask) {
+               drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;
+               goto unlock;
+       }
+
        for_each_cpu(cpu, drv->cpumask) {
                struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
 
@@ -415,5 +422,8 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
                        dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;
        }
 
+unlock:
+       spin_unlock(&cpuidle_driver_lock);
+
        mutex_unlock(&cpuidle_lock);
 }
index 425149e..57f6944 100644 (file)
 #include <linux/printk.h>
 #include <linux/hrtimer.h>
 #include <linux/of.h>
+#include <linux/pm_qos.h>
 #include "governor.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/devfreq.h>
 
+#define HZ_PER_KHZ     1000
+
 static struct class *devfreq_class;
 
 /*
@@ -99,6 +102,54 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
 }
 
 /**
+ * get_freq_range() - Get the current freq range
+ * @devfreq:   the devfreq instance
+ * @min_freq:  the min frequency
+ * @max_freq:  the max frequency
+ *
+ * This takes into consideration all constraints.
+ */
+static void get_freq_range(struct devfreq *devfreq,
+                          unsigned long *min_freq,
+                          unsigned long *max_freq)
+{
+       unsigned long *freq_table = devfreq->profile->freq_table;
+       s32 qos_min_freq, qos_max_freq;
+
+       lockdep_assert_held(&devfreq->lock);
+
+       /*
+        * Initialize minimum/maximum frequency from freq table.
+        * The devfreq drivers can initialize this in either ascending or
+        * descending order and devfreq core supports both.
+        */
+       if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
+               *min_freq = freq_table[0];
+               *max_freq = freq_table[devfreq->profile->max_state - 1];
+       } else {
+               *min_freq = freq_table[devfreq->profile->max_state - 1];
+               *max_freq = freq_table[0];
+       }
+
+       /* Apply constraints from PM QoS */
+       qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
+                                            DEV_PM_QOS_MIN_FREQUENCY);
+       qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
+                                            DEV_PM_QOS_MAX_FREQUENCY);
+       *min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
+       if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
+               *max_freq = min(*max_freq,
+                               (unsigned long)HZ_PER_KHZ * qos_max_freq);
+
+       /* Apply constraints from OPP interface */
+       *min_freq = max(*min_freq, devfreq->scaling_min_freq);
+       *max_freq = min(*max_freq, devfreq->scaling_max_freq);
+
+       if (*min_freq > *max_freq)
+               *min_freq = *max_freq;
+}
+
+/**
  * devfreq_get_freq_level() - Lookup freq_table for the frequency
  * @devfreq:   the devfreq instance
  * @freq:      the target frequency
@@ -351,16 +402,7 @@ int update_devfreq(struct devfreq *devfreq)
        err = devfreq->governor->get_target_freq(devfreq, &freq);
        if (err)
                return err;
-
-       /*
-        * Adjust the frequency with user freq, QoS and available freq.
-        *
-        * List from the highest priority
-        * max_freq
-        * min_freq
-        */
-       max_freq = min(devfreq->scaling_max_freq, devfreq->max_freq);
-       min_freq = max(devfreq->scaling_min_freq, devfreq->min_freq);
+       get_freq_range(devfreq, &min_freq, &max_freq);
 
        if (freq < min_freq) {
                freq = min_freq;
@@ -568,26 +610,69 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
                                 void *devp)
 {
        struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
-       int ret;
+       int err = -EINVAL;
 
        mutex_lock(&devfreq->lock);
 
        devfreq->scaling_min_freq = find_available_min_freq(devfreq);
-       if (!devfreq->scaling_min_freq) {
-               mutex_unlock(&devfreq->lock);
-               return -EINVAL;
-       }
+       if (!devfreq->scaling_min_freq)
+               goto out;
 
        devfreq->scaling_max_freq = find_available_max_freq(devfreq);
        if (!devfreq->scaling_max_freq) {
-               mutex_unlock(&devfreq->lock);
-               return -EINVAL;
+               devfreq->scaling_max_freq = ULONG_MAX;
+               goto out;
        }
 
-       ret = update_devfreq(devfreq);
+       err = update_devfreq(devfreq);
+
+out:
        mutex_unlock(&devfreq->lock);
+       if (err)
+               dev_err(devfreq->dev.parent,
+                       "failed to update frequency from OPP notifier (%d)\n",
+                       err);
 
-       return ret;
+       return NOTIFY_OK;
+}
+
+/**
+ * qos_notifier_call() - Common handler for QoS constraints.
+ * @devfreq:    the devfreq instance.
+ */
+static int qos_notifier_call(struct devfreq *devfreq)
+{
+       int err;
+
+       mutex_lock(&devfreq->lock);
+       err = update_devfreq(devfreq);
+       mutex_unlock(&devfreq->lock);
+       if (err)
+               dev_err(devfreq->dev.parent,
+                       "failed to update frequency from PM QoS (%d)\n",
+                       err);
+
+       return NOTIFY_OK;
+}
+
+/**
+ * qos_min_notifier_call() - Callback for QoS min_freq changes.
+ * @nb:                Should be devfreq->nb_min
+ */
+static int qos_min_notifier_call(struct notifier_block *nb,
+                                        unsigned long val, void *ptr)
+{
+       return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
+}
+
+/**
+ * qos_max_notifier_call() - Callback for QoS max_freq changes.
+ * @nb:                Should be devfreq->nb_max
+ */
+static int qos_max_notifier_call(struct notifier_block *nb,
+                                        unsigned long val, void *ptr)
+{
+       return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
 }
 
 /**
@@ -599,16 +684,36 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
 static void devfreq_dev_release(struct device *dev)
 {
        struct devfreq *devfreq = to_devfreq(dev);
+       int err;
 
        mutex_lock(&devfreq_list_lock);
-       if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
-               mutex_unlock(&devfreq_list_lock);
-               dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
-               return;
-       }
        list_del(&devfreq->node);
        mutex_unlock(&devfreq_list_lock);
 
+       err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
+                                        DEV_PM_QOS_MAX_FREQUENCY);
+       if (err && err != -ENOENT)
+               dev_warn(dev->parent,
+                       "Failed to remove max_freq notifier: %d\n", err);
+       err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
+                                        DEV_PM_QOS_MIN_FREQUENCY);
+       if (err && err != -ENOENT)
+               dev_warn(dev->parent,
+                       "Failed to remove min_freq notifier: %d\n", err);
+
+       if (dev_pm_qos_request_active(&devfreq->user_max_freq_req)) {
+               err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
+               if (err)
+                       dev_warn(dev->parent,
+                               "Failed to remove max_freq request: %d\n", err);
+       }
+       if (dev_pm_qos_request_active(&devfreq->user_min_freq_req)) {
+               err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
+               if (err)
+                       dev_warn(dev->parent,
+                               "Failed to remove min_freq request: %d\n", err);
+       }
+
        if (devfreq->profile->exit)
                devfreq->profile->exit(devfreq->dev.parent);
 
@@ -660,6 +765,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->dev.parent = dev;
        devfreq->dev.class = devfreq_class;
        devfreq->dev.release = devfreq_dev_release;
+       INIT_LIST_HEAD(&devfreq->node);
        devfreq->profile = profile;
        strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
        devfreq->previous_freq = profile->initial_freq;
@@ -681,7 +787,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
                err = -EINVAL;
                goto err_dev;
        }
-       devfreq->min_freq = devfreq->scaling_min_freq;
 
        devfreq->scaling_max_freq = find_available_max_freq(devfreq);
        if (!devfreq->scaling_max_freq) {
@@ -689,7 +794,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
                err = -EINVAL;
                goto err_dev;
        }
-       devfreq->max_freq = devfreq->scaling_max_freq;
 
        devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
        atomic_set(&devfreq->suspend_count, 0);
@@ -730,6 +834,28 @@ struct devfreq *devfreq_add_device(struct device *dev,
 
        mutex_unlock(&devfreq->lock);
 
+       err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
+                                    DEV_PM_QOS_MIN_FREQUENCY, 0);
+       if (err < 0)
+               goto err_devfreq;
+       err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
+                                    DEV_PM_QOS_MAX_FREQUENCY,
+                                    PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
+       if (err < 0)
+               goto err_devfreq;
+
+       devfreq->nb_min.notifier_call = qos_min_notifier_call;
+       err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_min,
+                                     DEV_PM_QOS_MIN_FREQUENCY);
+       if (err)
+               goto err_devfreq;
+
+       devfreq->nb_max.notifier_call = qos_max_notifier_call;
+       err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_max,
+                                     DEV_PM_QOS_MAX_FREQUENCY);
+       if (err)
+               goto err_devfreq;
+
        mutex_lock(&devfreq_list_lock);
 
        governor = try_then_request_governor(devfreq->governor_name);
@@ -1303,41 +1429,37 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
        unsigned long value;
        int ret;
 
+       /*
+        * Protect against theoretical sysfs writes between
+        * device_add and dev_pm_qos_add_request
+        */
+       if (!dev_pm_qos_request_active(&df->user_min_freq_req))
+               return -EAGAIN;
+
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
                return -EINVAL;
 
-       mutex_lock(&df->lock);
-
-       if (value) {
-               if (value > df->max_freq) {
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-       } else {
-               unsigned long *freq_table = df->profile->freq_table;
-
-               /* Get minimum frequency according to sorting order */
-               if (freq_table[0] < freq_table[df->profile->max_state - 1])
-                       value = freq_table[0];
-               else
-                       value = freq_table[df->profile->max_state - 1];
-       }
+       /* Round down to kHz for PM QoS */
+       ret = dev_pm_qos_update_request(&df->user_min_freq_req,
+                                       value / HZ_PER_KHZ);
+       if (ret < 0)
+               return ret;
 
-       df->min_freq = value;
-       update_devfreq(df);
-       ret = count;
-unlock:
-       mutex_unlock(&df->lock);
-       return ret;
+       return count;
 }
 
 static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct devfreq *df = to_devfreq(dev);
+       unsigned long min_freq, max_freq;
 
-       return sprintf(buf, "%lu\n", max(df->scaling_min_freq, df->min_freq));
+       mutex_lock(&df->lock);
+       get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
+
+       return sprintf(buf, "%lu\n", min_freq);
 }
 
 static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
@@ -1347,33 +1469,37 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
        unsigned long value;
        int ret;
 
+       /*
+        * Protect against theoretical sysfs writes between
+        * device_add and dev_pm_qos_add_request
+        */
+       if (!dev_pm_qos_request_active(&df->user_max_freq_req))
+               return -EINVAL;
+
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
                return -EINVAL;
 
-       mutex_lock(&df->lock);
-
-       if (value) {
-               if (value < df->min_freq) {
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-       } else {
-               unsigned long *freq_table = df->profile->freq_table;
+       /*
+        * PM QoS frequencies are in kHz so we need to convert. Convert by
+        * rounding upwards so that the acceptable interval never shrinks.
+        *
+        * For example if the user writes "666666666" to sysfs this value will
+        * be converted to 666667 kHz and back to 666667000 Hz before an OPP
+        * lookup, this ensures that an OPP of 666666666Hz is still accepted.
+        *
+        * A value of zero means "no limit".
+        */
+       if (value)
+               value = DIV_ROUND_UP(value, HZ_PER_KHZ);
+       else
+               value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
 
-               /* Get maximum frequency according to sorting order */
-               if (freq_table[0] < freq_table[df->profile->max_state - 1])
-                       value = freq_table[df->profile->max_state - 1];
-               else
-                       value = freq_table[0];
-       }
+       ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
+       if (ret < 0)
+               return ret;
 
-       df->max_freq = value;
-       update_devfreq(df);
-       ret = count;
-unlock:
-       mutex_unlock(&df->lock);
-       return ret;
+       return count;
 }
 static DEVICE_ATTR_RW(min_freq);
 
@@ -1381,8 +1507,13 @@ static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct devfreq *df = to_devfreq(dev);
+       unsigned long min_freq, max_freq;
+
+       mutex_lock(&df->lock);
+       get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
 
-       return sprintf(buf, "%lu\n", min(df->scaling_max_freq, df->max_freq));
+       return sprintf(buf, "%lu\n", max_freq);
 }
 static DEVICE_ATTR_RW(max_freq);
 
index 76fb072..5a5a1da 100644 (file)
@@ -221,7 +221,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
        a_fences = get_fences(a, &a_num_fences);
        b_fences = get_fences(b, &b_num_fences);
        if (a_num_fences > INT_MAX - b_num_fences)
-               return NULL;
+               goto err;
 
        num_fences = a_num_fences + b_num_fences;
 
index c9a0efc..d4077db 100644 (file)
 
 #include <asm/early_ioremap.h>
 
+static const struct console *earlycon_console __initdata;
 static const struct font_desc *font;
 static u32 efi_x, efi_y;
 static u64 fb_base;
 static pgprot_t fb_prot;
+static void *efi_fb;
+
+/*
+ * EFI earlycon needs to use early_memremap() to map the framebuffer.
+ * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
+ * memremap() should be used instead. memremap() will be available after
+ * paging_init() which is earlier than initcall callbacks. Thus adding this
+ * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
+ */
+static int __init efi_earlycon_remap_fb(void)
+{
+       /* bail if there is no bootconsole or it has been disabled already */
+       if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+               return 0;
+
+       if (pgprot_val(fb_prot) == pgprot_val(PAGE_KERNEL))
+               efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WB);
+       else
+               efi_fb = memremap(fb_base, screen_info.lfb_size, MEMREMAP_WC);
+
+       return efi_fb ? 0 : -ENOMEM;
+}
+early_initcall(efi_earlycon_remap_fb);
+
+static int __init efi_earlycon_unmap_fb(void)
+{
+       /* unmap the bootconsole fb unless keep_bootcon has left it enabled */
+       if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
+               memunmap(efi_fb);
+       return 0;
+}
+late_initcall(efi_earlycon_unmap_fb);
 
 static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
 {
+       if (efi_fb)
+               return efi_fb + start;
+
        return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
 }
 
 static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
 {
+       if (efi_fb)
+               return;
+
        early_memunmap(addr, len);
 }
 
@@ -201,6 +240,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
                efi_earlycon_scroll_up();
 
        device->con->write = efi_earlycon_write;
+       earlycon_console = device->con;
        return 0;
 }
 EARLYCON_DECLARE(efifb, efi_earlycon_setup);
index d101f07..2b02cb1 100644 (file)
@@ -681,7 +681,7 @@ device_initcall(efi_load_efivars);
                { name },                                  \
                { prop },                                  \
                offsetof(struct efi_fdt_params, field),    \
-               FIELD_SIZEOF(struct efi_fdt_params, field) \
+               sizeof_field(struct efi_fdt_params, field) \
        }
 
 struct params {
@@ -979,6 +979,24 @@ static int __init efi_memreserve_map_root(void)
        return 0;
 }
 
+static int efi_mem_reserve_iomem(phys_addr_t addr, u64 size)
+{
+       struct resource *res, *parent;
+
+       res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+       if (!res)
+               return -ENOMEM;
+
+       res->name       = "reserved";
+       res->flags      = IORESOURCE_MEM;
+       res->start      = addr;
+       res->end        = addr + size - 1;
+
+       /* we expect a conflict with a 'System RAM' region */
+       parent = request_resource_conflict(&iomem_resource, res);
+       return parent ? request_resource(parent, res) : 0;
+}
+
 int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
        struct linux_efi_memreserve *rsv;
@@ -1003,7 +1021,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
                        rsv->entry[index].size = size;
 
                        memunmap(rsv);
-                       return 0;
+                       return efi_mem_reserve_iomem(addr, size);
                }
                memunmap(rsv);
        }
@@ -1013,6 +1031,12 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
        if (!rsv)
                return -ENOMEM;
 
+       rc = efi_mem_reserve_iomem(__pa(rsv), SZ_4K);
+       if (rc) {
+               free_page((unsigned long)rsv);
+               return rc;
+       }
+
        /*
         * The memremap() call above assumes that a linux_efi_memreserve entry
         * never crosses a page boundary, so let's ensure that this remains true
@@ -1029,7 +1053,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
        efi_memreserve_root->next = __pa(rsv);
        spin_unlock(&efi_mem_reserve_persistent_lock);
 
-       return 0;
+       return efi_mem_reserve_iomem(addr, size);
 }
 
 static int __init efi_memreserve_root_init(void)
index 0101ca4..b7bf1e9 100644 (file)
@@ -84,30 +84,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 }
 
 static efi_status_t
-__gop_query32(efi_system_table_t *sys_table_arg,
-             struct efi_graphics_output_protocol_32 *gop32,
-             struct efi_graphics_output_mode_info **info,
-             unsigned long *size, u64 *fb_base)
-{
-       struct efi_graphics_output_protocol_mode_32 *mode;
-       efi_graphics_output_protocol_query_mode query_mode;
-       efi_status_t status;
-       unsigned long m;
-
-       m = gop32->mode;
-       mode = (struct efi_graphics_output_protocol_mode_32 *)m;
-       query_mode = (void *)(unsigned long)gop32->query_mode;
-
-       status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
-                                 info);
-       if (status != EFI_SUCCESS)
-               return status;
-
-       *fb_base = mode->frame_buffer_base;
-       return status;
-}
-
-static efi_status_t
 setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
             efi_guid_t *proto, unsigned long size, void **gop_handle)
 {
@@ -119,7 +95,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
        u64 fb_base;
        struct efi_pixel_bitmask pixel_info;
        int pixel_format;
-       efi_status_t status = EFI_NOT_FOUND;
+       efi_status_t status;
        u32 *handles = (u32 *)(unsigned long)gop_handle;
        int i;
 
@@ -128,6 +104,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        nr_gops = size / sizeof(u32);
        for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_protocol_mode_32 *mode;
                struct efi_graphics_output_mode_info *info = NULL;
                efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
                bool conout_found = false;
@@ -145,9 +122,11 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query32(sys_table_arg, gop32, &info, &size,
-                                      &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+               mode = (void *)(unsigned long)gop32->mode;
+               info = (void *)(unsigned long)mode->info;
+               current_fb_base = mode->frame_buffer_base;
+
+               if ((!first_gop || conout_found) &&
                    info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -175,7 +154,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        /* Did we find any GOPs? */
        if (!first_gop)
-               goto out;
+               return EFI_NOT_FOUND;
 
        /* EFI framebuffer */
        si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -197,32 +176,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
        si->lfb_size = si->lfb_linelength * si->lfb_height;
 
        si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-       return status;
-}
-
-static efi_status_t
-__gop_query64(efi_system_table_t *sys_table_arg,
-             struct efi_graphics_output_protocol_64 *gop64,
-             struct efi_graphics_output_mode_info **info,
-             unsigned long *size, u64 *fb_base)
-{
-       struct efi_graphics_output_protocol_mode_64 *mode;
-       efi_graphics_output_protocol_query_mode query_mode;
-       efi_status_t status;
-       unsigned long m;
-
-       m = gop64->mode;
-       mode = (struct efi_graphics_output_protocol_mode_64 *)m;
-       query_mode = (void *)(unsigned long)gop64->query_mode;
-
-       status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
-                                 info);
-       if (status != EFI_SUCCESS)
-               return status;
 
-       *fb_base = mode->frame_buffer_base;
-       return status;
+       return EFI_SUCCESS;
 }
 
 static efi_status_t
@@ -237,7 +192,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
        u64 fb_base;
        struct efi_pixel_bitmask pixel_info;
        int pixel_format;
-       efi_status_t status = EFI_NOT_FOUND;
+       efi_status_t status;
        u64 *handles = (u64 *)(unsigned long)gop_handle;
        int i;
 
@@ -246,6 +201,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        nr_gops = size / sizeof(u64);
        for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_protocol_mode_64 *mode;
                struct efi_graphics_output_mode_info *info = NULL;
                efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
                bool conout_found = false;
@@ -263,9 +219,11 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query64(sys_table_arg, gop64, &info, &size,
-                                      &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+               mode = (void *)(unsigned long)gop64->mode;
+               info = (void *)(unsigned long)mode->info;
+               current_fb_base = mode->frame_buffer_base;
+
+               if ((!first_gop || conout_found) &&
                    info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -293,7 +251,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        /* Did we find any GOPs? */
        if (!first_gop)
-               goto out;
+               return EFI_NOT_FOUND;
 
        /* EFI framebuffer */
        si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -315,8 +273,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
        si->lfb_size = si->lfb_linelength * si->lfb_height;
 
        si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-       return status;
+
+       return EFI_SUCCESS;
 }
 
 /*
index 76b0c35..de1a9a1 100644 (file)
@@ -81,6 +81,9 @@ static int __init efi_rci2_sysfs_init(void)
        struct kobject *tables_kobj;
        int ret = -ENOMEM;
 
+       if (rci2_table_phys == EFI_INVALID_TABLE_ADDR)
+               return 0;
+
        rci2_base = memremap(rci2_table_phys,
                             sizeof(struct rci2_table_global_hdr),
                             MEMREMAP_WB);
index dc27b1a..b696e45 100644 (file)
 #include "gpiolib.h"
 #include "gpiolib-of.h"
 
+/**
+ * of_gpio_spi_cs_get_count() - special GPIO counting for SPI
+ * Some elder GPIO controllers need special quirks. Currently we handle
+ * the Freescale GPIO controller with bindings that doesn't use the
+ * established "cs-gpios" for chip selects but instead rely on
+ * "gpios" for the chip select lines. If we detect this, we redirect
+ * the counting of "cs-gpios" to count "gpios" transparent to the
+ * driver.
+ */
+static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id)
+{
+       struct device_node *np = dev->of_node;
+
+       if (!IS_ENABLED(CONFIG_SPI_MASTER))
+               return 0;
+       if (!con_id || strcmp(con_id, "cs"))
+               return 0;
+       if (!of_device_is_compatible(np, "fsl,spi") &&
+           !of_device_is_compatible(np, "aeroflexgaisler,spictrl"))
+               return 0;
+       return of_gpio_named_count(np, "gpios");
+}
+
 /*
  * This is used by external users of of_gpio_count() from <linux/of_gpio.h>
  *
@@ -35,6 +58,10 @@ int of_gpio_get_count(struct device *dev, const char *con_id)
        char propname[32];
        unsigned int i;
 
+       ret = of_gpio_spi_cs_get_count(dev, con_id);
+       if (ret > 0)
+               return ret;
+
        for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
                if (con_id)
                        snprintf(propname, sizeof(propname), "%s-%s",
index d968c24..0d12ebf 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 menu "ACP (Audio CoProcessor) Configuration"
 
 config DRM_AMD_ACP
index 2e98c01..9375e7f 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 config DRM_AMDGPU_SI
        bool "Enable amdgpu support for SI parts"
        depends on DRM_AMDGPU
index 2cdaf3b..6614d8a 100644 (file)
@@ -604,11 +604,8 @@ void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
                        continue;
                }
 
-               for (i = 0; i < num_entities; i++) {
-                       mutex_lock(&ctx->adev->lock_reset);
+               for (i = 0; i < num_entities; i++)
                        drm_sched_entity_fini(&ctx->entities[0][i].entity);
-                       mutex_unlock(&ctx->adev->lock_reset);
-               }
        }
 }
 
index 16fbd2b..4043ebc 100644 (file)
@@ -268,23 +268,29 @@ static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
 {
        u32 tmp;
 
-       /* Put DF on broadcast mode */
-       adev->df_funcs->enable_broadcast_mode(adev, true);
-
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG)) {
-               tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-               tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-               tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
-               WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-       } else {
-               tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-               tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-               tmp |= DF_V3_6_MGCG_DISABLE;
-               WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-       }
+       if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
+               /* Put DF on broadcast mode */
+               adev->df_funcs->enable_broadcast_mode(adev, true);
+
+               if (enable) {
+                       tmp = RREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater);
+                       tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+                       tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
+                       WREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+               } else {
+                       tmp = RREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater);
+                       tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+                       tmp |= DF_V3_6_MGCG_DISABLE;
+                       WREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+               }
 
-       /* Exit broadcast mode */
-       adev->df_funcs->enable_broadcast_mode(adev, false);
+               /* Exit broadcast mode */
+               adev->df_funcs->enable_broadcast_mode(adev, false);
+       }
 }
 
 static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
index f2c1b02..ba9e53a 100644 (file)
@@ -117,10 +117,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffff9fff, 0x00001188),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070104),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
@@ -162,10 +165,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0xffff0fff, 0x10000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffffbfff, 0x00000188),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070105),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
index 983db77..52a647d 100644 (file)
@@ -6146,7 +6146,23 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
        bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
        bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
 
-       /* EVENT_WRITE_EOP - flush caches, send int */
+       /* Workaround for cache flush problems. First send a dummy EOP
+        * event down the pipe with seq one below.
+        */
+       amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
+       amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
+                                EOP_TC_ACTION_EN |
+                                EOP_TC_WB_ACTION_EN |
+                                EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+                                EVENT_INDEX(5)));
+       amdgpu_ring_write(ring, addr & 0xfffffffc);
+       amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
+                               DATA_SEL(1) | INT_SEL(0));
+       amdgpu_ring_write(ring, lower_32_bits(seq - 1));
+       amdgpu_ring_write(ring, upper_32_bits(seq - 1));
+
+       /* Then send the real EOP event down the pipe:
+        * EVENT_WRITE_EOP - flush caches, send int */
        amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
        amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
                                 EOP_TC_ACTION_EN |
@@ -6888,7 +6904,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
                5 +  /* COND_EXEC */
                7 +  /* PIPELINE_SYNC */
                VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 9 + /* VM_FLUSH */
-               8 +  /* FENCE for VM_FLUSH */
+               12 +  /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                4 + /* double SWITCH_BUFFER,
                       the first COND_EXEC jump to the place just
@@ -6900,7 +6916,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
                31 + /* DE_META */
                3 + /* CNTX_CTRL */
                5 + /* HDP_INVL */
-               8 + 8 + /* FENCE x2 */
+               12 + 12 + /* FENCE x2 */
                2, /* SWITCH_BUFFER */
        .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
        .emit_ib = gfx_v8_0_ring_emit_ib_gfx,
index 2324695..f572533 100644 (file)
@@ -219,6 +219,21 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
        return req;
 }
 
+/**
+ * gmc_v10_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+                                      uint32_t vmhub)
+{
+       return ((vmhub == AMDGPU_MMHUB_0 ||
+                vmhub == AMDGPU_MMHUB_1) &&
+               (!amdgpu_sriov_vf(adev)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -229,6 +244,7 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
 static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
                                   unsigned int vmhub, uint32_t flush_type)
 {
+       bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub);
        struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
        u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
        /* Use register 17 for GART */
@@ -244,8 +260,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1) {
+       if (use_semaphore) {
                for (i = 0; i < adev->usec_timeout; i++) {
                        /* a read return value of 1 means semaphore acuqire */
                        tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
@@ -278,8 +293,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
        }
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
@@ -369,6 +383,7 @@ error_alloc:
 static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                             unsigned vmid, uint64_t pd_addr)
 {
+       bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
        struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
        unsigned eng = ring->vm_inv_eng;
@@ -381,8 +396,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /* a read return value of 1 means semaphore acuqire */
                amdgpu_ring_emit_reg_wait(ring,
                                          hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
@@ -398,8 +412,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            req, 1 << vmid);
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
index 3c355fb..a5b68b5 100644 (file)
@@ -416,6 +416,24 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
        return req;
 }
 
+/**
+ * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+                                      uint32_t vmhub)
+{
+       return ((vmhub == AMDGPU_MMHUB_0 ||
+                vmhub == AMDGPU_MMHUB_1) &&
+               (!amdgpu_sriov_vf(adev)) &&
+               (!(adev->asic_type == CHIP_RAVEN &&
+                  adev->rev_id < 0x8 &&
+                  adev->pdev->device == 0x15d8)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -435,6 +453,7 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
 static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
                                        uint32_t vmhub, uint32_t flush_type)
 {
+       bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
        const unsigned eng = 17;
        u32 j, tmp;
        struct amdgpu_vmhub *hub;
@@ -468,8 +487,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1) {
+       if (use_semaphore) {
                for (j = 0; j < adev->usec_timeout; j++) {
                        /* a read return value of 1 means semaphore acuqire */
                        tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
@@ -499,8 +517,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
        }
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
@@ -518,6 +535,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            unsigned vmid, uint64_t pd_addr)
 {
+       bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
        uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
@@ -531,8 +549,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /* a read return value of 1 means semaphore acuqire */
                amdgpu_ring_emit_reg_wait(ring,
                                          hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
@@ -548,8 +565,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            req, 1 << vmid);
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
index ba0e680..b3672d1 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 #
 # Heterogenous system architecture configuration
 #
index 313183b..ae161fe 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 menu "Display Engine Configuration"
        depends on DRM && DRM_AMDGPU
 
index 7873abe..5c3fcaa 100644 (file)
@@ -1625,6 +1625,7 @@ static enum bp_result construct_integrated_info(
                /* Don't need to check major revision as they are all 1 */
                switch (revision.minor) {
                case 11:
+               case 12:
                        result = get_integrated_info_v11(bp, info);
                        break;
                default:
index 790a2d2..35c55e5 100644 (file)
@@ -471,12 +471,28 @@ static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
 
 }
 
+static bool rn_are_clock_states_equal(struct dc_clocks *a,
+               struct dc_clocks *b)
+{
+       if (a->dispclk_khz != b->dispclk_khz)
+               return false;
+       else if (a->dppclk_khz != b->dppclk_khz)
+               return false;
+       else if (a->dcfclk_khz != b->dcfclk_khz)
+               return false;
+       else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+               return false;
+
+       return true;
+}
+
+
 static struct clk_mgr_funcs dcn21_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = rn_update_clocks,
        .init_clocks = rn_init_clocks,
        .enable_pme_wa = rn_enable_pme_wa,
-       /* .dump_clk_registers = rn_dump_clk_registers, */
+       .are_clock_states_equal = rn_are_clock_states_equal,
        .notify_wm_ranges = rn_notify_wm_ranges
 };
 
@@ -518,36 +534,83 @@ struct clk_bw_params rn_bw_params = {
                .num_entries = 4,
        },
 
-       .wm_table = {
-               .entries = {
-                       {
-                               .wm_inst = WM_A,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_B,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_C,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_D,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
+};
+
+struct wm_table ddr4_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 6.09,
+                       .sr_enter_plus_exit_time_us = 7.14,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
                },
        }
 };
 
+struct wm_table lpddr4_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+       }
+};
+
+
 static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 {
        int i;
@@ -561,7 +624,7 @@ static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsi
        return 0;
 }
 
-static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct hw_asic_id *asic_id)
+static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info)
 {
        int i, j = 0;
 
@@ -593,8 +656,8 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
                bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
        }
 
-       bw_params->vram_type = asic_id->vram_type;
-       bw_params->num_channels = asic_id->vram_width / DDR4_DRAM_WIDTH;
+       bw_params->vram_type = bios_info->memory_type;
+       bw_params->num_channels = bios_info->ma_channel_number;
 
        for (i = 0; i < WM_SET_COUNT; i++) {
                bw_params->wm_table.entries[i].wm_inst = i;
@@ -669,15 +732,24 @@ void rn_clk_mgr_construct(
                        ASSERT(clk_mgr->base.dprefclk_khz == 600000);
                        clk_mgr->base.dprefclk_khz = 600000;
                }
+
+               if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
+                       rn_bw_params.wm_table = lpddr4_wm_table;
+               } else {
+                       rn_bw_params.wm_table = ddr4_wm_table;
+               }
        }
 
        dce_clock_read_ss_info(clk_mgr);
 
+
        clk_mgr->base.bw_params = &rn_bw_params;
 
        if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
                pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
-               rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
+               if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+                       rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info);
+               }
        }
 
        if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
index 12ba6fd..62d8289 100644 (file)
@@ -372,7 +372,7 @@ bool dc_link_is_dp_sink_present(struct dc_link *link)
 
        if (GPIO_RESULT_OK != dal_ddc_open(
                ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
-               dal_gpio_destroy_ddc(&ddc);
+               dal_ddc_close(ddc);
 
                return present;
        }
index 7f904d5..8178919 100644 (file)
@@ -586,7 +586,7 @@ bool dal_ddc_service_query_ddc_data(
 bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
                struct aux_payload *payload)
 {
-       uint8_t retrieved = 0;
+       uint32_t retrieved = 0;
        bool ret = 0;
 
        if (!ddc)
index 0f59b68..504055f 100644 (file)
@@ -3522,7 +3522,14 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
        if (link_enc->funcs->fec_set_enable &&
                        link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
                if (link->fec_state == dc_link_fec_ready && enable) {
-                       msleep(1);
+                       /* Accord to DP spec, FEC enable sequence can first
+                        * be transmitted anytime after 1000 LL codes have
+                        * been transmitted on the link after link training
+                        * completion. Using 1 lane RBR should have the maximum
+                        * time for transmitting 1000 LL codes which is 6.173 us.
+                        * So use 7 microseconds delay instead.
+                        */
+                       udelay(7);
                        link_enc->funcs->fec_set_enable(link_enc, true);
                        link->fec_state = dc_link_fec_enabled;
                } else if (link->fec_state == dc_link_fec_enabled && !enable) {
index e472608..793c0ce 100644 (file)
@@ -583,6 +583,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
        uint8_t reply;
        bool payload_reply = true;
        enum aux_channel_operation_result operation_result;
+       bool retry_on_defer = false;
+
        int aux_ack_retries = 0,
                aux_defer_retries = 0,
                aux_i2c_defer_retries = 0,
@@ -613,8 +615,10 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        break;
 
                        case AUX_TRANSACTION_REPLY_AUX_DEFER:
-                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
+                               retry_on_defer = true;
+                               /* fall through */
+                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                                if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
                                        goto fail;
                                } else {
@@ -647,15 +651,24 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        break;
 
                case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-                       if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
-                               goto fail;
-                       else {
-                               /*
-                                * DP 1.4, 2.8.2:  AUX Transaction Response/Reply Timeouts
-                                * According to the DP spec there should be 3 retries total
-                                * with a 400us wait inbetween each. Hardware already waits
-                                * for 550us therefore no wait is required here.
-                                */
+                       // Check whether a DEFER had occurred before the timeout.
+                       // If so, treat timeout as a DEFER.
+                       if (retry_on_defer) {
+                               if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES)
+                                       goto fail;
+                               else if (payload->defer_delay > 0)
+                                       msleep(payload->defer_delay);
+                       } else {
+                               if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
+                                       goto fail;
+                               else {
+                                       /*
+                                        * DP 1.4, 2.8.2:  AUX Transaction Response/Reply Timeouts
+                                        * According to the DP spec there should be 3 retries total
+                                        * with a 400us wait inbetween each. Hardware already waits
+                                        * for 550us therefore no wait is required here.
+                                        */
+                               }
                        }
                        break;
 
index 0979333..23ff2f1 100644 (file)
@@ -923,7 +923,9 @@ static const struct resource_caps res_cap_nv14 = {
                .num_dwb = 1,
                .num_ddc = 5,
                .num_vmid = 16,
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
                .num_dsc = 5,
+#endif
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
@@ -1536,13 +1538,20 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
 
 static void acquire_dsc(struct resource_context *res_ctx,
                        const struct resource_pool *pool,
-                       struct display_stream_compressor **dsc)
+                       struct display_stream_compressor **dsc,
+                       int pipe_idx)
 {
        int i;
 
        ASSERT(*dsc == NULL);
        *dsc = NULL;
 
+       if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
+               *dsc = pool->dscs[pipe_idx];
+               res_ctx->is_dsc_acquired[pipe_idx] = true;
+               return;
+       }
+
        /* Find first free DSC */
        for (i = 0; i < pool->res_cap->num_dsc; i++)
                if (!res_ctx->is_dsc_acquired[i]) {
@@ -1585,7 +1594,7 @@ static enum dc_status add_dsc_to_stream_resource(struct dc *dc,
                if (pipe_ctx->stream != dc_stream)
                        continue;
 
-               acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
+               acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc, i);
 
                /* The number of DSCs can be less than the number of pipes */
                if (!pipe_ctx->stream_res.dsc) {
@@ -1785,7 +1794,7 @@ bool dcn20_split_stream_for_odm(
        next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        if (next_odm_pipe->stream->timing.flags.DSC == 1) {
-               acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc);
+               acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
                ASSERT(next_odm_pipe->stream_res.dsc);
                if (next_odm_pipe->stream_res.dsc == NULL)
                        return false;
index 4b34016..fcb3877 100644 (file)
@@ -492,15 +492,23 @@ void enc2_stream_encoder_dp_unblank(
                                DP_VID_N_MUL, n_multiply);
        }
 
-       /* set DIG_START to 0x1 to reset FIFO */
+       /* make sure stream is disabled before resetting steer fifo */
+       REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
+       REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
 
+       /* set DIG_START to 0x1 to reset FIFO */
        REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
+       udelay(1);
 
        /* write 0 to take the FIFO out of reset */
 
        REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
 
-       /* switch DP encoder to CRTC data */
+       /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
+        * that it overflows during mode transition, and sometimes doesn't recover.
+        */
+       REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
+       udelay(10);
 
        REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
 
index 459bd9a..b29b2c9 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/slab.h>
+
 #include "dm_services.h"
 #include "dc.h"
 
@@ -257,7 +259,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
        .vmm_page_size_bytes = 4096,
        .dram_clock_change_latency_us = 23.84,
        .return_bus_width_bytes = 64,
-       .dispclk_dppclk_vco_speed_mhz = 3550,
+       .dispclk_dppclk_vco_speed_mhz = 3600,
        .xfc_bus_transport_time_us = 4,
        .xfc_xbuf_latency_tolerance_us = 4,
        .use_urgent_burst_bw = 1,
@@ -1000,6 +1002,8 @@ static void calculate_wm_set_for_vlevel(
        pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
 
        dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
+       dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
+       dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
 
        wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
        wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
@@ -1017,14 +1021,21 @@ static void calculate_wm_set_for_vlevel(
 
 static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
 {
+       int i;
+
        kernel_fpu_begin();
        if (dc->bb_overrides.sr_exit_time_ns) {
-               bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                         dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
+                                         dc->bb_overrides.sr_exit_time_ns / 1000.0;
+               }
        }
 
        if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
-               bb->sr_enter_plus_exit_time_us =
-                               dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                         dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us =
+                                         dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+               }
        }
 
        if (dc->bb_overrides.urgent_latency_ns) {
@@ -1032,9 +1043,12 @@ static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s
        }
 
        if (dc->bb_overrides.dram_clock_change_latency_ns) {
-               bb->dram_clock_change_latency_us =
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                       dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us =
                                dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+               }
        }
+
        kernel_fpu_end();
 }
 
index 9707372..641ffb7 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: MIT
 #
 # Makefile for the 'dsc' sub-component of DAL.
 
index 4e18e77..026e6a2 100644 (file)
@@ -69,6 +69,8 @@ struct wm_range_table_entry {
        unsigned int wm_inst;
        unsigned int wm_type;
        double pstate_latency_us;
+       double sr_exit_time_us;
+       double sr_enter_plus_exit_time_us;
        bool valid;
 };
 
index bb012cb..c7fbb9c 100644 (file)
@@ -42,7 +42,7 @@ struct aux_payload {
        bool write;
        bool mot;
        uint32_t address;
-       uint8_t length;
+       uint32_t length;
        uint8_t *data;
        /*
         * used to return the reply type of the transaction
index 16e69bb..5437b50 100644 (file)
@@ -37,8 +37,8 @@
 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
 /* Number of elements in the render times cache array */
 #define RENDER_TIMES_MAX_COUNT 10
-/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
-#define BTR_MAX_MARGIN 2500
+/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
+#define BTR_EXIT_MARGIN 2000
 /* Threshold to change BTR multiplier (to avoid frequent changes) */
 #define BTR_DRIFT_MARGIN 2000
 /*Threshold to exit fixed refresh rate*/
@@ -254,22 +254,24 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
        unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
        unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
        unsigned int frames_to_insert = 0;
+       unsigned int min_frame_duration_in_ns = 0;
+       unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
        unsigned int delta_from_mid_point_delta_in_us;
-       unsigned int max_render_time_in_us =
-                       in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
+
+       min_frame_duration_in_ns = ((unsigned int) (div64_u64(
+               (1000000000ULL * 1000000),
+               in_out_vrr->max_refresh_in_uhz)));
 
        /* Program BTR */
-       if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
+       if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) {
                /* Exit Below the Range */
                if (in_out_vrr->btr.btr_active) {
                        in_out_vrr->btr.frame_counter = 0;
                        in_out_vrr->btr.btr_active = false;
                }
-       } else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
+       } else if (last_render_time_in_us > max_render_time_in_us) {
                /* Enter Below the Range */
-               if (!in_out_vrr->btr.btr_active) {
-                       in_out_vrr->btr.btr_active = true;
-               }
+               in_out_vrr->btr.btr_active = true;
        }
 
        /* BTR set to "not active" so disengage */
@@ -325,9 +327,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                /* Choose number of frames to insert based on how close it
                 * can get to the mid point of the variable range.
                 */
-               if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us &&
-                               (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 ||
-                                               mid_point_frames_floor < 2)) {
+               if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
                        frames_to_insert = mid_point_frames_ceil;
                        delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
                                        delta_from_mid_point_in_us_1;
@@ -343,7 +343,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                if (in_out_vrr->btr.frames_to_insert != 0 &&
                                delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
                        if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
-                                       max_render_time_in_us) &&
+                                       in_out_vrr->max_duration_in_us) &&
                                ((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
                                        in_out_vrr->min_duration_in_us))
                                frames_to_insert = in_out_vrr->btr.frames_to_insert;
@@ -796,11 +796,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
                refresh_range = in_out_vrr->max_refresh_in_uhz -
                                in_out_vrr->min_refresh_in_uhz;
 
-               in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
-                               2 * in_out_vrr->min_duration_in_us;
-               if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
-                       in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
-
                in_out_vrr->supported = true;
        }
 
@@ -816,7 +811,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
        in_out_vrr->btr.inserted_duration_in_us = 0;
        in_out_vrr->btr.frames_to_insert = 0;
        in_out_vrr->btr.frame_counter = 0;
-
        in_out_vrr->btr.mid_point_in_us =
                                (in_out_vrr->min_duration_in_us +
                                 in_out_vrr->max_duration_in_us) / 2;
index dbe7835..dc18784 100644 (file)
@@ -92,7 +92,6 @@ struct mod_vrr_params_btr {
        uint32_t inserted_duration_in_us;
        uint32_t frames_to_insert;
        uint32_t frame_counter;
-       uint32_t margin_in_us;
 };
 
 struct mod_vrr_params_fixed_refresh {
index ce3566c..cc71a10 100644 (file)
@@ -1313,12 +1313,17 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
                                        "VR",
                                        "COMPUTE",
                                        "CUSTOM"};
+       static const char *title[] = {
+                       "PROFILE_INDEX(NAME)"};
        uint32_t i, size = 0;
        int16_t workload_type = 0;
 
        if (!smu->pm_enabled || !buf)
                return -EINVAL;
 
+       size += sprintf(buf + size, "%16s\n",
+                       title[0]);
+
        for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
                /*
                 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
index 7ae087b..88b6fca 100644 (file)
@@ -1313,6 +1313,7 @@ static int gsc_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
 
+       component_del(dev, &gsc_component_ops);
        pm_runtime_dont_use_autosuspend(dev);
        pm_runtime_disable(dev);
 
index c7c2b34..2a27fb5 100644 (file)
@@ -3986,6 +3986,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED)
                intel_hdcp_enable(to_intel_connector(conn_state->connector),
+                                 crtc_state->cpu_transcoder,
                                  (u8)conn_state->hdcp_content_type);
 }
 
@@ -4089,7 +4090,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED ||
            content_protection_type_changed)
-               intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
+               intel_hdcp_enable(connector,
+                                 crtc_state->cpu_transcoder,
+                                 (u8)conn_state->hdcp_content_type);
 }
 
 static void
index ce1b64f..12ba747 100644 (file)
@@ -3688,6 +3688,151 @@ static const struct i915_power_well_desc icl_power_wells[] = {
        },
 };
 
+static const struct i915_power_well_desc ehl_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = true,
+               .domains = POWER_DOMAIN_MASK,
+               .ops = &i9xx_always_on_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+       },
+       {
+               .name = "power well 1",
+               /* Handled by the DMC firmware */
+               .always_on = true,
+               .domains = 0,
+               .ops = &hsw_power_well_ops,
+               .id = SKL_DISP_PW_1,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_1,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "DC off",
+               .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
+               .ops = &gen9_dc_off_power_well_ops,
+               .id = SKL_DISP_DC_OFF,
+       },
+       {
+               .name = "power well 2",
+               .domains = ICL_PW_2_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = SKL_DISP_PW_2,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_2,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "power well 3",
+               .domains = ICL_PW_3_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_3,
+                       .hsw.irq_pipe_mask = BIT(PIPE_B),
+                       .hsw.has_vga = true,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "DDI A IO",
+               .domains = ICL_DDI_IO_A_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
+               },
+       },
+       {
+               .name = "DDI B IO",
+               .domains = ICL_DDI_IO_B_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
+               },
+       },
+       {
+               .name = "DDI C IO",
+               .domains = ICL_DDI_IO_C_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
+               },
+       },
+       {
+               .name = "DDI D IO",
+               .domains = ICL_DDI_IO_D_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_D,
+               },
+       },
+       {
+               .name = "AUX A",
+               .domains = ICL_AUX_A_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
+               },
+       },
+       {
+               .name = "AUX B",
+               .domains = ICL_AUX_B_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
+               },
+       },
+       {
+               .name = "AUX C",
+               .domains = ICL_AUX_C_TC1_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
+               },
+       },
+       {
+               .name = "AUX D",
+               .domains = ICL_AUX_D_TC2_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_D,
+               },
+       },
+       {
+               .name = "power well 4",
+               .domains = ICL_PW_4_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_4,
+                       .hsw.has_fuses = true,
+                       .hsw.irq_pipe_mask = BIT(PIPE_C),
+               },
+       },
+};
+
 static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "always-on",
@@ -3832,7 +3977,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX A",
                .domains = TGL_AUX_A_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -3842,7 +3987,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX B",
                .domains = TGL_AUX_B_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -3852,7 +3997,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX C",
                .domains = TGL_AUX_C_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4162,6 +4307,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
         */
        if (IS_GEN(dev_priv, 12)) {
                err = set_power_wells(power_domains, tgl_power_wells);
+       } else if (IS_ELKHARTLAKE(dev_priv)) {
+               err = set_power_wells(power_domains, ehl_power_wells);
        } else if (IS_GEN(dev_priv, 11)) {
                err = set_power_wells(power_domains, icl_power_wells);
        } else if (IS_CANNONLAKE(dev_priv)) {
index 050655a..b05b219 100644 (file)
@@ -2414,9 +2414,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        intel_psr_compute_config(intel_dp, pipe_config);
 
-       intel_hdcp_transcoder_config(intel_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 3111eca..2061663 100644 (file)
@@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
                return 0;
 
        /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
-       if (IS_GEMINILAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return 0;
 
        if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
index f1f41ca..a448815 100644 (file)
@@ -1821,23 +1821,6 @@ enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder)
        }
 }
 
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder)
-{
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       struct intel_hdcp *hdcp = &connector->hdcp;
-
-       if (!hdcp->shim)
-               return;
-
-       if (INTEL_GEN(dev_priv) >= 12) {
-               mutex_lock(&hdcp->mutex);
-               hdcp->cpu_transcoder = cpu_transcoder;
-               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
-               mutex_unlock(&hdcp->mutex);
-       }
-}
-
 static inline int initialize_hdcp_port_data(struct intel_connector *connector,
                                            const struct intel_hdcp_shim *shim)
 {
@@ -1959,8 +1942,10 @@ int intel_hdcp_init(struct intel_connector *connector,
        return 0;
 }
 
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_hdcp *hdcp = &connector->hdcp;
        unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
        int ret = -EINVAL;
@@ -1972,6 +1957,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
        WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
        hdcp->content_type = content_type;
 
+       if (INTEL_GEN(dev_priv) >= 12) {
+               hdcp->cpu_transcoder = cpu_transcoder;
+               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
+       }
+
        /*
         * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
         * is capable of HDCP2.2, it is preferred to use HDCP2.2.
index 41c1053..f3c3272 100644 (file)
@@ -21,11 +21,10 @@ enum transcoder;
 void intel_hdcp_atomic_check(struct drm_connector *connector,
                             struct drm_connector_state *old_state,
                             struct drm_connector_state *new_state);
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder);
 int intel_hdcp_init(struct intel_connector *connector,
                    const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type);
 int intel_hdcp_disable(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
index f6f5312..f56fffc 100644 (file)
@@ -2489,9 +2489,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
                return -EINVAL;
        }
 
-       intel_hdcp_transcoder_config(intel_hdmi->attached_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 337ba17..4238527 100644 (file)
@@ -2167,8 +2167,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        ext_data.fpriv = file->driver_priv;
        if (client_is_banned(ext_data.fpriv)) {
                DRM_DEBUG("client %s[%d] banned from creating ctx\n",
-                         current->comm,
-                         pid_nr(get_task_pid(current, PIDTYPE_PID)));
+                         current->comm, task_pid_nr(current));
                return -EIO;
        }
 
index f0998f1..bc3a672 100644 (file)
@@ -2694,6 +2694,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
        err = eb_submit(&eb);
 err_request:
        add_to_client(eb.request, file);
+       i915_request_get(eb.request);
        i915_request_add(eb.request);
 
        if (fences)
@@ -2709,6 +2710,7 @@ err_request:
                        fput(out_fence->file);
                }
        }
+       i915_request_put(eb.request);
 
 err_batch_unpin:
        if (eb.batch_flags & I915_DISPATCH_SECURE)
index 9fdefbd..75dd0e0 100644 (file)
@@ -845,12 +845,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
        }
 }
 
-static void unwind_wa_tail(struct i915_request *rq)
-{
-       rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
-       assert_ring_tail_valid(rq->ring, rq->tail);
-}
-
 static struct i915_request *
 __unwind_incomplete_requests(struct intel_engine_cs *engine)
 {
@@ -863,12 +857,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
        list_for_each_entry_safe_reverse(rq, rn,
                                         &engine->active.requests,
                                         sched.link) {
-
                if (i915_request_completed(rq))
                        continue; /* XXX */
 
                __i915_request_unsubmit(rq);
-               unwind_wa_tail(rq);
 
                /*
                 * Push the request back into the queue for later resubmission.
@@ -1161,13 +1153,29 @@ execlists_schedule_out(struct i915_request *rq)
        i915_request_put(rq);
 }
 
-static u64 execlists_update_context(const struct i915_request *rq)
+static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->hw_context;
-       u64 desc;
+       u64 desc = ce->lrc_desc;
+       u32 tail;
 
-       ce->lrc_reg_state[CTX_RING_TAIL] =
-               intel_ring_set_tail(rq->ring, rq->tail);
+       /*
+        * WaIdleLiteRestore:bdw,skl
+        *
+        * We should never submit the context with the same RING_TAIL twice
+        * just in case we submit an empty ring, which confuses the HW.
+        *
+        * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
+        * the normal request to be able to always advance the RING_TAIL on
+        * subsequent resubmissions (for lite restore). Should that fail us,
+        * and we try and submit the same tail again, force the context
+        * reload.
+        */
+       tail = intel_ring_set_tail(rq->ring, rq->tail);
+       if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
+               desc |= CTX_DESC_FORCE_RESTORE;
+       ce->lrc_reg_state[CTX_RING_TAIL] = tail;
+       rq->tail = rq->wa_tail;
 
        /*
         * Make sure the context image is complete before we submit it to HW.
@@ -1186,13 +1194,11 @@ static u64 execlists_update_context(const struct i915_request *rq)
         */
        mb();
 
-       desc = ce->lrc_desc;
-       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
-
        /* Wa_1607138340:tgl */
        if (IS_TGL_REVID(rq->i915, TGL_REVID_A0, TGL_REVID_A0))
                desc |= CTX_DESC_FORCE_RESTORE;
 
+       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
        return desc;
 }
 
@@ -1703,16 +1709,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                                return;
                        }
-
-                       /*
-                        * WaIdleLiteRestore:bdw,skl
-                        * Apply the wa NOOPs to prevent
-                        * ring:HEAD == rq:TAIL as we resubmit the
-                        * request. See gen8_emit_fini_breadcrumb() for
-                        * where we prepare the padding after the
-                        * end of the request.
-                        */
-                       last->tail = last->wa_tail;
                }
        }
 
@@ -4120,17 +4116,18 @@ static void virtual_context_destroy(struct kref *kref)
        for (n = 0; n < ve->num_siblings; n++) {
                struct intel_engine_cs *sibling = ve->siblings[n];
                struct rb_node *node = &ve->nodes[sibling->id].rb;
+               unsigned long flags;
 
                if (RB_EMPTY_NODE(node))
                        continue;
 
-               spin_lock_irq(&sibling->active.lock);
+               spin_lock_irqsave(&sibling->active.lock, flags);
 
                /* Detachment is lazily performed in the execlists tasklet */
                if (!RB_EMPTY_NODE(node))
                        rb_erase_cached(node, &sibling->execlists.virtual);
 
-               spin_unlock_irq(&sibling->active.lock);
+               spin_unlock_irqrestore(&sibling->active.lock, flags);
        }
        GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));
 
index e451298..2477a1e 100644 (file)
 
 #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
 
+static int vgpu_pin_dma_address(struct intel_vgpu *vgpu,
+                               unsigned long size,
+                               dma_addr_t dma_addr)
+{
+       int ret = 0;
+
+       if (intel_gvt_hypervisor_dma_pin_guest_page(vgpu, dma_addr))
+               ret = -EINVAL;
+
+       return ret;
+}
+
+static void vgpu_unpin_dma_address(struct intel_vgpu *vgpu,
+                                  dma_addr_t dma_addr)
+{
+       intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, dma_addr);
+}
+
 static int vgpu_gem_get_pages(
                struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+       struct intel_vgpu *vgpu;
        struct sg_table *st;
        struct scatterlist *sg;
-       int i, ret;
+       int i, j, ret;
        gen8_pte_t __iomem *gtt_entries;
        struct intel_vgpu_fb_info *fb_info;
        u32 page_num;
@@ -51,6 +70,10 @@ static int vgpu_gem_get_pages(
        if (WARN_ON(!fb_info))
                return -ENODEV;
 
+       vgpu = fb_info->obj->vgpu;
+       if (WARN_ON(!vgpu))
+               return -ENODEV;
+
        st = kmalloc(sizeof(*st), GFP_KERNEL);
        if (unlikely(!st))
                return -ENOMEM;
@@ -64,21 +87,53 @@ static int vgpu_gem_get_pages(
        gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
                (fb_info->start >> PAGE_SHIFT);
        for_each_sg(st->sgl, sg, page_num, i) {
+               dma_addr_t dma_addr =
+                       GEN8_DECODE_PTE(readq(&gtt_entries[i]));
+               if (vgpu_pin_dma_address(vgpu, PAGE_SIZE, dma_addr)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
                sg->offset = 0;
                sg->length = PAGE_SIZE;
-               sg_dma_address(sg) =
-                       GEN8_DECODE_PTE(readq(&gtt_entries[i]));
                sg_dma_len(sg) = PAGE_SIZE;
+               sg_dma_address(sg) = dma_addr;
        }
 
        __i915_gem_object_set_pages(obj, st, PAGE_SIZE);
+out:
+       if (ret) {
+               dma_addr_t dma_addr;
+
+               for_each_sg(st->sgl, sg, i, j) {
+                       dma_addr = sg_dma_address(sg);
+                       if (dma_addr)
+                               vgpu_unpin_dma_address(vgpu, dma_addr);
+               }
+               sg_free_table(st);
+               kfree(st);
+       }
+
+       return ret;
 
-       return 0;
 }
 
 static void vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
                struct sg_table *pages)
 {
+       struct scatterlist *sg;
+
+       if (obj->base.dma_buf) {
+               struct intel_vgpu_fb_info *fb_info = obj->gvt_info;
+               struct intel_vgpu_dmabuf_obj *obj = fb_info->obj;
+               struct intel_vgpu *vgpu = obj->vgpu;
+               int i;
+
+               for_each_sg(pages->sgl, sg, fb_info->size, i)
+                       vgpu_unpin_dma_address(vgpu,
+                                              sg_dma_address(sg));
+       }
+
        sg_free_table(pages);
        kfree(pages);
 }
@@ -163,6 +218,7 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
        drm_gem_private_object_init(dev, &obj->base,
                roundup(info->size, PAGE_SIZE));
        i915_gem_object_init(obj, &intel_vgpu_gem_ops, &lock_class);
+       i915_gem_object_set_readonly(obj);
 
        obj->read_domains = I915_GEM_DOMAIN_GTT;
        obj->write_domain = 0;
index bb9fe6b..1043e6d 100644 (file)
@@ -341,6 +341,10 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                        gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
                        engine_mask |= BIT(VCS1);
                }
+               if (data & GEN9_GRDOM_GUC) {
+                       gvt_dbg_mmio("vgpu%d: request GUC Reset\n", vgpu->id);
+                       vgpu_vreg_t(vgpu, GUC_STATUS) |= GS_MIA_IN_RESET;
+               }
                engine_mask &= INTEL_INFO(vgpu->gvt->dev_priv)->engine_mask;
        }
 
@@ -1636,6 +1640,16 @@ static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
        return 0;
 }
 
+static int guc_status_read(struct intel_vgpu *vgpu,
+                          unsigned int offset, void *p_data,
+                          unsigned int bytes)
+{
+       /* keep MIA_IN_RESET before clearing */
+       read_vreg(vgpu, offset, p_data, bytes);
+       vgpu_vreg(vgpu, offset) &= ~GS_MIA_IN_RESET;
+       return 0;
+}
+
 static int mmio_read_from_hw(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
 {
@@ -2672,6 +2686,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
        MMIO_DH(EDP_PSR_IMR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
        MMIO_DH(EDP_PSR_IIR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
+       MMIO_DH(GUC_STATUS, D_ALL, guc_status_read, NULL);
+
        return 0;
 }
 
index 4862fb1..b19a3b1 100644 (file)
@@ -62,6 +62,8 @@ struct intel_gvt_mpt {
                                  unsigned long size, dma_addr_t *dma_addr);
        void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
 
+       int (*dma_pin_guest_page)(unsigned long handle, dma_addr_t dma_addr);
+
        int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
                              unsigned long mfn, unsigned int nr, bool map);
        int (*set_trap_area)(unsigned long handle, u64 start, u64 end,
index 04a5a0d..3259a1f 100644 (file)
@@ -1916,6 +1916,28 @@ err_unlock:
        return ret;
 }
 
+static int kvmgt_dma_pin_guest_page(unsigned long handle, dma_addr_t dma_addr)
+{
+       struct kvmgt_guest_info *info;
+       struct gvt_dma *entry;
+       int ret = 0;
+
+       if (!handle_valid(handle))
+               return -ENODEV;
+
+       info = (struct kvmgt_guest_info *)handle;
+
+       mutex_lock(&info->vgpu->vdev.cache_lock);
+       entry = __gvt_cache_find_dma_addr(info->vgpu, dma_addr);
+       if (entry)
+               kref_get(&entry->ref);
+       else
+               ret = -ENOMEM;
+       mutex_unlock(&info->vgpu->vdev.cache_lock);
+
+       return ret;
+}
+
 static void __gvt_dma_release(struct kref *ref)
 {
        struct gvt_dma *entry = container_of(ref, typeof(*entry), ref);
@@ -2027,6 +2049,7 @@ static struct intel_gvt_mpt kvmgt_mpt = {
        .gfn_to_mfn = kvmgt_gfn_to_pfn,
        .dma_map_guest_page = kvmgt_dma_map_guest_page,
        .dma_unmap_guest_page = kvmgt_dma_unmap_guest_page,
+       .dma_pin_guest_page = kvmgt_dma_pin_guest_page,
        .set_opregion = kvmgt_set_opregion,
        .set_edid = kvmgt_set_edid,
        .get_vfio_device = kvmgt_get_vfio_device,
index 0f94401..9ad224d 100644 (file)
@@ -255,6 +255,21 @@ static inline void intel_gvt_hypervisor_dma_unmap_guest_page(
 }
 
 /**
+ * intel_gvt_hypervisor_dma_pin_guest_page - pin guest dma buf
+ * @vgpu: a vGPU
+ * @dma_addr: guest dma addr
+ *
+ * Returns:
+ * 0 on success, negative error code if failed.
+ */
+static inline int
+intel_gvt_hypervisor_dma_pin_guest_page(struct intel_vgpu *vgpu,
+                                       dma_addr_t dma_addr)
+{
+       return intel_gvt_host.mpt->dma_pin_guest_page(vgpu->handle, dma_addr);
+}
+
+/**
  * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
  * @vgpu: a vGPU
  * @gfn: guest PFN
index d5a6e4e..85bd9bf 100644 (file)
@@ -212,9 +212,9 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
  */
 void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu)
 {
-       mutex_lock(&vgpu->gvt->lock);
+       mutex_lock(&vgpu->vgpu_lock);
        vgpu->active = true;
-       mutex_unlock(&vgpu->gvt->lock);
+       mutex_unlock(&vgpu->vgpu_lock);
 }
 
 /**
index b9eb6b3..d034fa4 100644 (file)
@@ -45,6 +45,7 @@
 #include "gem/i915_gem_context.h"
 #include "gem/i915_gem_ioctls.h"
 #include "gem/i915_gem_pm.h"
+#include "gt/intel_context.h"
 #include "gt/intel_engine_user.h"
 #include "gt/intel_gt.h"
 #include "gt/intel_gt_pm.h"
@@ -1053,6 +1054,18 @@ out:
        return err;
 }
 
+static int __intel_context_flush_retire(struct intel_context *ce)
+{
+       struct intel_timeline *tl;
+
+       tl = intel_context_timeline_lock(ce);
+       if (IS_ERR(tl))
+               return PTR_ERR(tl);
+
+       intel_context_timeline_unlock(tl);
+       return 0;
+}
+
 static int __intel_engines_record_defaults(struct intel_gt *gt)
 {
        struct i915_request *requests[I915_NUM_ENGINES] = {};
@@ -1121,13 +1134,20 @@ err_rq:
                if (!rq)
                        continue;
 
-               /* We want to be able to unbind the state from the GGTT */
-               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
-
+               GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT,
+                                    &rq->hw_context->flags));
                state = rq->hw_context->state;
                if (!state)
                        continue;
 
+               /* Serialise with retirement on another CPU */
+               err = __intel_context_flush_retire(rq->hw_context);
+               if (err)
+                       goto out;
+
+               /* We want to be able to unbind the state from the GGTT */
+               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
+
                /*
                 * As we will hold a reference to the logical state, it will
                 * not be torn down with the context, and importantly the
index 65d7c2e..2ae14bc 100644 (file)
@@ -2078,20 +2078,12 @@ gen8_update_reg_state_unlocked(const struct intel_context *ce,
        u32 *reg_state = ce->lrc_reg_state;
        int i;
 
-       if (IS_GEN(stream->perf->i915, 12)) {
-               u32 format = stream->oa_buffer.format;
+       reg_state[ctx_oactxctrl + 1] =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
 
-               reg_state[ctx_oactxctrl + 1] =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (stream->oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               reg_state[ctx_oactxctrl + 1] =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 0; !!ctx_flexeu0 && i < ARRAY_SIZE(flex_regs); i++)
+       for (i = 0; i < ARRAY_SIZE(flex_regs); i++)
                reg_state[ctx_flexeu0 + i * 2 + 1] =
                        oa_config_flex_reg(stream->oa_config, flex_regs[i]);
 
@@ -2224,34 +2216,51 @@ static int gen8_configure_context(struct i915_gem_context *ctx,
        return err;
 }
 
-static int gen12_emit_oar_config(struct intel_context *ce, bool enable)
+static int gen12_configure_oar_context(struct i915_perf_stream *stream, bool enable)
 {
-       struct i915_request *rq;
-       u32 *cs;
-       int err = 0;
-
-       rq = i915_request_create(ce);
-       if (IS_ERR(rq))
-               return PTR_ERR(rq);
-
-       cs = intel_ring_begin(rq, 4);
-       if (IS_ERR(cs)) {
-               err = PTR_ERR(cs);
-               goto out;
-       }
-
-       *cs++ = MI_LOAD_REGISTER_IMM(1);
-       *cs++ = i915_mmio_reg_offset(RING_CONTEXT_CONTROL(ce->engine->mmio_base));
-       *cs++ = _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
-                             enable ? GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE : 0);
-       *cs++ = MI_NOOP;
+       int err;
+       struct intel_context *ce = stream->pinned_ctx;
+       u32 format = stream->oa_buffer.format;
+       struct flex regs_context[] = {
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+                       enable ? GEN8_OA_COUNTER_RESUME : 0,
+               },
+       };
+       /* Offsets in regs_lri are not used since this configuration is only
+        * applied using LRI. Initialize the correct offsets for posterity.
+        */
+#define GEN12_OAR_OACONTROL_OFFSET 0x5B0
+       struct flex regs_lri[] = {
+               {
+                       GEN12_OAR_OACONTROL,
+                       GEN12_OAR_OACONTROL_OFFSET + 1,
+                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
+                       (enable ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0)
+               },
+               {
+                       RING_CONTEXT_CONTROL(ce->engine->mmio_base),
+                       CTX_CONTEXT_CONTROL,
+                       _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
+                                     enable ?
+                                     GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE :
+                                     0)
+               },
+       };
 
-       intel_ring_advance(rq, cs);
+       /* Modify the context image of pinned context with regs_context*/
+       err = intel_context_lock_pinned(ce);
+       if (err)
+               return err;
 
-out:
-       i915_request_add(rq);
+       err = gen8_modify_context(ce, regs_context, ARRAY_SIZE(regs_context));
+       intel_context_unlock_pinned(ce);
+       if (err)
+               return err;
 
-       return err;
+       /* Apply regs_lri using LRI with pinned context */
+       return gen8_modify_self(ce, regs_lri, ARRAY_SIZE(regs_lri));
 }
 
 /*
@@ -2277,53 +2286,16 @@ out:
  *   per-context OA state.
  *
  * Note: it's only the RCS/Render context that has any OA state.
+ * Note: the first flex register passed must always be R_PWR_CLK_STATE
  */
-static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
-                                     const struct i915_oa_config *oa_config)
+static int oa_configure_all_contexts(struct i915_perf_stream *stream,
+                                    struct flex *regs,
+                                    size_t num_regs)
 {
        struct drm_i915_private *i915 = stream->perf->i915;
-       /* The MMIO offsets for Flex EU registers aren't contiguous */
-       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
-#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
-       struct flex regs[] = {
-               {
-                       GEN8_R_PWR_CLK_STATE,
-                       CTX_R_PWR_CLK_STATE,
-               },
-               {
-                       IS_GEN(i915, 12) ?
-                       GEN12_OAR_OACONTROL : GEN8_OACTXCONTROL,
-                       stream->perf->ctx_oactxctrl_offset + 1,
-               },
-               { EU_PERF_CNTL0, ctx_flexeuN(0) },
-               { EU_PERF_CNTL1, ctx_flexeuN(1) },
-               { EU_PERF_CNTL2, ctx_flexeuN(2) },
-               { EU_PERF_CNTL3, ctx_flexeuN(3) },
-               { EU_PERF_CNTL4, ctx_flexeuN(4) },
-               { EU_PERF_CNTL5, ctx_flexeuN(5) },
-               { EU_PERF_CNTL6, ctx_flexeuN(6) },
-       };
-#undef ctx_flexeuN
        struct intel_engine_cs *engine;
        struct i915_gem_context *ctx, *cn;
-       size_t array_size = IS_GEN(i915, 12) ? 2 : ARRAY_SIZE(regs);
-       int i, err;
-
-       if (IS_GEN(i915, 12)) {
-               u32 format = stream->oa_buffer.format;
-
-               regs[1].value =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               regs[1].value =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 2; !!ctx_flexeu0 && i < array_size; i++)
-               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+       int err;
 
        lockdep_assert_held(&stream->perf->lock);
 
@@ -2353,7 +2325,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                spin_unlock(&i915->gem.contexts.lock);
 
-               err = gen8_configure_context(ctx, regs, array_size);
+               err = gen8_configure_context(ctx, regs, num_regs);
                if (err) {
                        i915_gem_context_put(ctx);
                        return err;
@@ -2378,7 +2350,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                regs[0].value = intel_sseu_make_rpcs(i915, &ce->sseu);
 
-               err = gen8_modify_self(ce, regs, array_size);
+               err = gen8_modify_self(ce, regs, num_regs);
                if (err)
                        return err;
        }
@@ -2386,6 +2358,56 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
        return 0;
 }
 
+static int gen12_configure_all_contexts(struct i915_perf_stream *stream,
+                                       const struct i915_oa_config *oa_config)
+{
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+       };
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
+static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
+                                     const struct i915_oa_config *oa_config)
+{
+       /* The MMIO offsets for Flex EU registers aren't contiguous */
+       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
+#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+               },
+               { EU_PERF_CNTL0, ctx_flexeuN(0) },
+               { EU_PERF_CNTL1, ctx_flexeuN(1) },
+               { EU_PERF_CNTL2, ctx_flexeuN(2) },
+               { EU_PERF_CNTL3, ctx_flexeuN(3) },
+               { EU_PERF_CNTL4, ctx_flexeuN(4) },
+               { EU_PERF_CNTL5, ctx_flexeuN(5) },
+               { EU_PERF_CNTL6, ctx_flexeuN(6) },
+       };
+#undef ctx_flexeuN
+       int i;
+
+       regs[1].value =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
+
+       for (i = 2; i < ARRAY_SIZE(regs); i++)
+               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
 static int gen8_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
@@ -2464,7 +2486,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * to make sure all slices/subslices are ON before writing to NOA
         * registers.
         */
-       ret = lrc_configure_all_contexts(stream, oa_config);
+       ret = gen12_configure_all_contexts(stream, oa_config);
        if (ret)
                return ret;
 
@@ -2474,8 +2496,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * requested this.
         */
        if (stream->ctx) {
-               ret = gen12_emit_oar_config(stream->pinned_ctx,
-                                           oa_config != NULL);
+               ret = gen12_configure_oar_context(stream, true);
                if (ret)
                        return ret;
        }
@@ -2509,11 +2530,11 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream)
        struct intel_uncore *uncore = stream->uncore;
 
        /* Reset all contexts' slices/subslices configurations. */
-       lrc_configure_all_contexts(stream, NULL);
+       gen12_configure_all_contexts(stream, NULL);
 
        /* disable the context save/restore or OAR counters */
        if (stream->ctx)
-               gen12_emit_oar_config(stream->pinned_ctx, false);
+               gen12_configure_oar_context(stream, false);
 
        /* Make sure we disable noa to save power. */
        intel_uncore_rmw(uncore, RPM_CONFIG1, GEN10_GT_NOA_ENABLE, 0);
@@ -2713,7 +2734,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
                return -EINVAL;
        }
 
-       if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
+       if (!(props->sample_flags & SAMPLE_OA_REPORT) &&
+           (INTEL_GEN(perf->i915) < 12 || !stream->ctx)) {
                DRM_DEBUG("Only OA report sampling supported\n");
                return -EINVAL;
        }
@@ -2745,7 +2767,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 
        format_size = perf->oa_formats[props->oa_format].size;
 
-       stream->sample_flags |= SAMPLE_OA_REPORT;
+       stream->sample_flags = props->sample_flags;
        stream->sample_size += format_size;
 
        stream->oa_buffer.format_size = format_size;
@@ -2854,7 +2876,11 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
                return;
 
        stream = engine->i915->perf.exclusive_stream;
-       if (stream)
+       /*
+        * For gen12, only CTX_R_PWR_CLK_STATE needs update, but the caller
+        * is already doing that, so nothing to be done for gen12 here.
+        */
+       if (stream && INTEL_GEN(stream->perf->i915) < 12)
                gen8_update_reg_state_unlocked(ce, stream);
 }
 
index 73079b5..4fd3d76 100644 (file)
@@ -9405,11 +9405,9 @@ enum skl_power_gate {
 #define _ICL_AUX_REG_IDX(pw_idx)       ((pw_idx) - ICL_PW_CTL_IDX_AUX_A)
 #define _ICL_AUX_ANAOVRD1_A            0x162398
 #define _ICL_AUX_ANAOVRD1_B            0x6C398
-#define _TGL_AUX_ANAOVRD1_C            0x160398
 #define ICL_AUX_ANAOVRD1(pw_idx)       _MMIO(_PICK(_ICL_AUX_REG_IDX(pw_idx), \
                                                    _ICL_AUX_ANAOVRD1_A, \
-                                                   _ICL_AUX_ANAOVRD1_B, \
-                                                   _TGL_AUX_ANAOVRD1_C))
+                                                   _ICL_AUX_ANAOVRD1_B))
 #define   ICL_AUX_ANAOVRD1_LDO_BYPASS  (1 << 7)
 #define   ICL_AUX_ANAOVRD1_ENABLE      (1 << 0)
 
@@ -11994,7 +11992,7 @@ enum skl_power_gate {
 /* This register controls the Display State Buffer (DSB) engines. */
 #define _DSBSL_INSTANCE_BASE           0x70B00
 #define DSBSL_INSTANCE(pipe, id)       (_DSBSL_INSTANCE_BASE + \
-                                        (pipe) * 0x1000 + (id) * 100)
+                                        (pipe) * 0x1000 + (id) * 0x100)
 #define DSB_HEAD(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x0)
 #define DSB_TAIL(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4)
 #define DSB_CTRL(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8)
index bbd71af..765bec8 100644 (file)
@@ -300,11 +300,11 @@ void i915_request_retire_upto(struct i915_request *rq)
 }
 
 static int
-__i915_request_await_execution(struct i915_request *rq,
-                              struct i915_request *signal,
-                              void (*hook)(struct i915_request *rq,
-                                           struct dma_fence *signal),
-                              gfp_t gfp)
+__await_execution(struct i915_request *rq,
+                 struct i915_request *signal,
+                 void (*hook)(struct i915_request *rq,
+                              struct dma_fence *signal),
+                 gfp_t gfp)
 {
        struct execute_cb *cb;
 
@@ -341,6 +341,8 @@ __i915_request_await_execution(struct i915_request *rq,
        }
        spin_unlock_irq(&signal->lock);
 
+       /* Copy across semaphore status as we need the same behaviour */
+       rq->sched.flags |= signal->sched.flags;
        return 0;
 }
 
@@ -811,31 +813,21 @@ already_busywaiting(struct i915_request *rq)
 }
 
 static int
-emit_semaphore_wait(struct i915_request *to,
-                   struct i915_request *from,
-                   gfp_t gfp)
+__emit_semaphore_wait(struct i915_request *to,
+                     struct i915_request *from,
+                     u32 seqno)
 {
        const int has_token = INTEL_GEN(to->i915) >= 12;
        u32 hwsp_offset;
-       int len;
+       int len, err;
        u32 *cs;
 
        GEM_BUG_ON(INTEL_GEN(to->i915) < 8);
 
-       /* Just emit the first semaphore we see as request space is limited. */
-       if (already_busywaiting(to) & from->engine->mask)
-               goto await_fence;
-
-       if (i915_request_await_start(to, from) < 0)
-               goto await_fence;
-
-       /* Only submit our spinner after the signaler is running! */
-       if (__i915_request_await_execution(to, from, NULL, gfp))
-               goto await_fence;
-
        /* We need to pin the signaler's HWSP until we are finished reading. */
-       if (intel_timeline_read_hwsp(from, to, &hwsp_offset))
-               goto await_fence;
+       err = intel_timeline_read_hwsp(from, to, &hwsp_offset);
+       if (err)
+               return err;
 
        len = 4;
        if (has_token)
@@ -858,7 +850,7 @@ emit_semaphore_wait(struct i915_request *to,
                 MI_SEMAPHORE_POLL |
                 MI_SEMAPHORE_SAD_GTE_SDD) +
                has_token;
-       *cs++ = from->fence.seqno;
+       *cs++ = seqno;
        *cs++ = hwsp_offset;
        *cs++ = 0;
        if (has_token) {
@@ -867,6 +859,28 @@ emit_semaphore_wait(struct i915_request *to,
        }
 
        intel_ring_advance(to, cs);
+       return 0;
+}
+
+static int
+emit_semaphore_wait(struct i915_request *to,
+                   struct i915_request *from,
+                   gfp_t gfp)
+{
+       /* Just emit the first semaphore we see as request space is limited. */
+       if (already_busywaiting(to) & from->engine->mask)
+               goto await_fence;
+
+       if (i915_request_await_start(to, from) < 0)
+               goto await_fence;
+
+       /* Only submit our spinner after the signaler is running! */
+       if (__await_execution(to, from, NULL, gfp))
+               goto await_fence;
+
+       if (__emit_semaphore_wait(to, from, from->fence.seqno))
+               goto await_fence;
+
        to->sched.semaphores |= from->engine->mask;
        to->sched.flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
        return 0;
@@ -980,6 +994,57 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence)
        return 0;
 }
 
+static bool intel_timeline_sync_has_start(struct intel_timeline *tl,
+                                         struct dma_fence *fence)
+{
+       return __intel_timeline_sync_is_later(tl,
+                                             fence->context,
+                                             fence->seqno - 1);
+}
+
+static int intel_timeline_sync_set_start(struct intel_timeline *tl,
+                                        const struct dma_fence *fence)
+{
+       return __intel_timeline_sync_set(tl, fence->context, fence->seqno - 1);
+}
+
+static int
+__i915_request_await_execution(struct i915_request *to,
+                              struct i915_request *from,
+                              void (*hook)(struct i915_request *rq,
+                                           struct dma_fence *signal))
+{
+       int err;
+
+       /* Submit both requests at the same time */
+       err = __await_execution(to, from, hook, I915_FENCE_GFP);
+       if (err)
+               return err;
+
+       /* Squash repeated depenendices to the same timelines */
+       if (intel_timeline_sync_has_start(i915_request_timeline(to),
+                                         &from->fence))
+               return 0;
+
+       /* Ensure both start together [after all semaphores in signal] */
+       if (intel_engine_has_semaphores(to->engine))
+               err = __emit_semaphore_wait(to, from, from->fence.seqno - 1);
+       else
+               err = i915_request_await_start(to, from);
+       if (err < 0)
+               return err;
+
+       /* Couple the dependency tree for PI on this exposed to->fence */
+       if (to->engine->schedule) {
+               err = i915_sched_node_add_dependency(&to->sched, &from->sched);
+               if (err < 0)
+                       return err;
+       }
+
+       return intel_timeline_sync_set_start(i915_request_timeline(to),
+                                            &from->fence);
+}
+
 int
 i915_request_await_execution(struct i915_request *rq,
                             struct dma_fence *fence,
@@ -1013,8 +1078,7 @@ i915_request_await_execution(struct i915_request *rq,
                if (dma_fence_is_i915(fence))
                        ret = __i915_request_await_execution(rq,
                                                             to_request(fence),
-                                                            hook,
-                                                            I915_FENCE_GFP);
+                                                            hook);
                else
                        ret = i915_sw_fence_await_dma_fence(&rq->submit, fence,
                                                            I915_FENCE_TIMEOUT,
index 010d67f..247a967 100644 (file)
@@ -474,7 +474,6 @@ void i915_sched_node_fini(struct i915_sched_node *node)
         * so we may be called out-of-order.
         */
        list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) {
-               GEM_BUG_ON(!node_signaled(dep->signaler));
                GEM_BUG_ON(!list_empty(&dep->dfs_link));
 
                list_del(&dep->wait_link);
index 07552cd..8538ee7 100644 (file)
@@ -78,12 +78,11 @@ static const struct dma_fence_ops fence_ops = {
 void dma_fence_work_init(struct dma_fence_work *f,
                         const struct dma_fence_work_ops *ops)
 {
+       f->ops = ops;
        spin_lock_init(&f->lock);
        dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0);
        i915_sw_fence_init(&f->chain, fence_notify);
        INIT_WORK(&f->work, fence_work);
-
-       f->ops = ops;
 }
 
 int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal)
index 809bff9..75ae6f4 100644 (file)
@@ -4291,8 +4291,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
                                &crtc_state->wm.skl.optimal.planes[plane_id];
 
                        if (plane_id == PLANE_CURSOR) {
-                               if (WARN_ON(wm->wm[level].min_ddb_alloc >
-                                           total[PLANE_CURSOR])) {
+                               if (wm->wm[level].min_ddb_alloc > total[PLANE_CURSOR]) {
+                                       WARN_ON(wm->wm[level].min_ddb_alloc != U16_MAX);
                                        blocks = U32_MAX;
                                        break;
                                }
index d6214d3..ef4c630 100644 (file)
@@ -935,11 +935,13 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
        for_each_available_child_of_node(dev->of_node, child) {
                panel = of_drm_find_panel(child);
                if (IS_ERR(panel)) {
-                       dev_err(dev, "failed to find panel try bridge (%lu)\n",
+                       dev_err(dev, "failed to find panel try bridge (%ld)\n",
                                PTR_ERR(panel));
+                       panel = NULL;
+
                        bridge = of_drm_find_bridge(child);
                        if (IS_ERR(bridge)) {
-                               dev_err(dev, "failed to find bridge (%lu)\n",
+                               dev_err(dev, "failed to find bridge (%ld)\n",
                                        PTR_ERR(bridge));
                                return PTR_ERR(bridge);
                        }
index 9ab27ae..1bd6b6d 100644 (file)
@@ -64,6 +64,25 @@ struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
        },
 };
 
+static const struct meson_cvbs_mode *
+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
+{
+       int i;
+
+       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+               if (drm_mode_match(req_mode, &meson_mode->mode,
+                                  DRM_MODE_MATCH_TIMINGS |
+                                  DRM_MODE_MATCH_CLOCK |
+                                  DRM_MODE_MATCH_FLAGS |
+                                  DRM_MODE_MATCH_3D_FLAGS))
+                       return meson_mode;
+       }
+
+       return NULL;
+}
+
 /* Connector */
 
 static void meson_cvbs_connector_destroy(struct drm_connector *connector)
@@ -136,14 +155,8 @@ static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
                                        struct drm_crtc_state *crtc_state,
                                        struct drm_connector_state *conn_state)
 {
-       int i;
-
-       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
-
-               if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
-                       return 0;
-       }
+       if (meson_cvbs_get_mode(&crtc_state->mode))
+               return 0;
 
        return -EINVAL;
 }
@@ -191,24 +204,17 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
+       const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
        struct meson_venc_cvbs *meson_venc_cvbs =
                                        encoder_to_meson_venc_cvbs(encoder);
        struct meson_drm *priv = meson_venc_cvbs->priv;
-       int i;
 
-       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+       if (meson_mode) {
+               meson_venci_cvbs_mode_set(priv, meson_mode->enci);
 
-               if (drm_mode_equal(mode, &meson_mode->mode)) {
-                       meson_venci_cvbs_mode_set(priv,
-                                                 meson_mode->enci);
-
-                       /* Setup 27MHz vclk2 for ENCI and VDAC */
-                       meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
-                                        MESON_VCLK_CVBS, MESON_VCLK_CVBS,
-                                        MESON_VCLK_CVBS, true);
-                       break;
-               }
+               /* Setup 27MHz vclk2 for ENCI and VDAC */
+               meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
+                                MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
        }
 }
 
index d43951c..b113876 100644 (file)
@@ -30,9 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400);
 static struct drm_driver driver;
 
 static const struct pci_device_id pciidlist[] = {
-       { PCI_VENDOR_ID_MATROX, 0x522, PCI_VENDOR_ID_SUN, 0x4852, 0, 0,
+       { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
-       { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
        { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
        { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
        { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
index 43df86c..24f7700 100644 (file)
@@ -114,6 +114,7 @@ struct nv50_head_atom {
                u8 nhsync:1;
                u8 nvsync:1;
                u8 depth:4;
+               u8 bpc;
        } or;
 
        /* Currently only used for MST */
index 549486f..63425e2 100644 (file)
@@ -326,9 +326,9 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
                         * same size as the native one (e.g. different
                         * refresh rate)
                         */
-                       if (adjusted_mode->hdisplay == native_mode->hdisplay &&
-                           adjusted_mode->vdisplay == native_mode->vdisplay &&
-                           adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+                       if (mode->hdisplay == native_mode->hdisplay &&
+                           mode->vdisplay == native_mode->vdisplay &&
+                           mode->type & DRM_MODE_TYPE_DRIVER)
                                break;
                        mode = native_mode;
                        asyc->scaler.full = true;
@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
                       struct drm_crtc_state *crtc_state,
                       struct drm_connector_state *conn_state)
 {
-       struct nouveau_connector *nv_connector =
-               nouveau_connector(conn_state->connector);
-       return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-                                          nv_connector->native_mode);
+       struct drm_connector *connector = conn_state->connector;
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+       int ret;
+
+       ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+                                         nv_connector->native_mode);
+       if (ret)
+               return ret;
+
+       if (crtc_state->mode_changed || crtc_state->connectors_changed)
+               asyh->or.bpc = connector->display_info.bpc;
+
+       return 0;
 }
 
 /******************************************************************************
@@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
        struct nv50_mstm *mstm = mstc->mstm;
        struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
        int slots;
+       int ret;
+
+       ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+                                         mstc->native);
+       if (ret)
+               return ret;
+
+       if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+               return 0;
+
+       /*
+        * When restoring duplicated states, we need to make sure that the bw
+        * remains the same and avoid recalculating it, as the connector's bpc
+        * may have changed after the state was duplicated
+        */
+       if (!state->duplicated) {
+               const int clock = crtc_state->adjusted_mode.clock;
 
-       if (crtc_state->mode_changed || crtc_state->connectors_changed) {
                /*
-                * When restoring duplicated states, we need to make sure that
-                * the bw remains the same and avoid recalculating it, as the
-                * connector's bpc may have changed after the state was
-                * duplicated
+                * XXX: Since we don't use HDR in userspace quite yet, limit
+                * the bpc to 8 to save bandwidth on the topology. In the
+                * future, we'll want to properly fix this by dynamically
+                * selecting the highest possible bpc that would fit in the
+                * topology
                 */
-               if (!state->duplicated) {
-                       const int bpp = connector->display_info.bpc * 3;
-                       const int clock = crtc_state->adjusted_mode.clock;
+               asyh->or.bpc = min(connector->display_info.bpc, 8U);
+               asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
+       }
 
-                       asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
-               }
+       slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
+                                             asyh->dp.pbn);
+       if (slots < 0)
+               return slots;
 
-               slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
-                                                     mstc->port,
-                                                     asyh->dp.pbn);
-               if (slots < 0)
-                       return slots;
+       asyh->dp.tu = slots;
 
-               asyh->dp.tu = slots;
-       }
+       return 0;
+}
 
-       return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-                                          mstc->native);
+static u8
+nv50_dp_bpc_to_depth(unsigned int bpc)
+{
+       switch (bpc) {
+       case  6: return 0x2;
+       case  8: return 0x5;
+       case 10: /* fall-through */
+       default: return 0x6;
+       }
 }
 
 static void
@@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
        struct nv50_mstm *mstm = NULL;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
-       u8 proto, depth;
+       u8 proto;
        bool r;
 
        drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
        else
                proto = 0x9;
 
-       switch (mstc->connector.display_info.bpc) {
-       case  6: depth = 0x2; break;
-       case  8: depth = 0x5; break;
-       case 10:
-       default: depth = 0x6; break;
-       }
-
-       mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
+       mstm->outp->update(mstm->outp, head->base.index, armh, proto,
+                          nv50_dp_bpc_to_depth(armh->or.bpc));
 
        msto->head = head;
        msto->mstc = mstc;
@@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *encoder)
                                        lvds.lvds.script |= 0x0200;
                        }
 
-                       if (nv_connector->base.display_info.bpc == 8)
+                       if (asyh->or.bpc == 8)
                                lvds.lvds.script |= 0x0200;
                }
 
                nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
                break;
        case DCB_OUTPUT_DP:
-               if (nv_connector->base.display_info.bpc == 6)
-                       depth = 0x2;
-               else
-               if (nv_connector->base.display_info.bpc == 8)
-                       depth = 0x5;
-               else
-                       depth = 0x6;
+               depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
 
                if (nv_encoder->link & 1)
                        proto = 0x8;
@@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *encoder)
        nv50_outp_acquire(nv_encoder);
 
        nv_connector = nouveau_encoder_connector_get(nv_encoder);
-       switch (nv_connector->base.display_info.bpc) {
+       switch (asyh->or.bpc) {
        case 10: asyh->or.depth = 0x6; break;
        case  8: asyh->or.depth = 0x5; break;
        case  6: asyh->or.depth = 0x2; break;
index 71c23bf..c9692df 100644 (file)
@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
                              struct nv50_head_atom *asyh,
                              struct nouveau_conn_atom *asyc)
 {
-       struct drm_connector *connector = asyc->state.connector;
        u32 mode = 0x00;
 
        if (asyc->dither.mode == DITHERING_MODE_AUTO) {
-               if (asyh->base.depth > connector->display_info.bpc * 3)
+               if (asyh->base.depth > asyh->or.bpc * 3)
                        mode = DITHERING_MODE_DYNAMIC2X2;
        } else {
                mode = asyc->dither.mode;
        }
 
        if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
-               if (connector->display_info.bpc >= 8)
+               if (asyh->or.bpc >= 8)
                        mode |= DITHERING_DEPTH_8BPC;
        } else {
                mode |= asyc->dither.depth;
index 5b41358..9a9a7f5 100644 (file)
@@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
 void
 nouveau_conn_reset(struct drm_connector *connector)
 {
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_conn_atom *asyc;
 
-       if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
-               return;
+       if (drm_drv_uses_atomic_modeset(connector->dev)) {
+               if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
+                       return;
+
+               if (connector->state)
+                       nouveau_conn_atomic_destroy_state(connector,
+                                                         connector->state);
+
+               __drm_atomic_helper_connector_reset(connector, &asyc->state);
+       } else {
+               asyc = &nv_connector->properties_state;
+       }
 
-       if (connector->state)
-               nouveau_conn_atomic_destroy_state(connector, connector->state);
-       __drm_atomic_helper_connector_reset(connector, &asyc->state);
        asyc->dither.mode = DITHERING_MODE_AUTO;
        asyc->dither.depth = DITHERING_DEPTH_AUTO;
        asyc->scaler.mode = DRM_MODE_SCALE_NONE;
@@ -276,8 +284,14 @@ void
 nouveau_conn_attach_properties(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct nouveau_conn_atom *armc;
+
+       if (drm_drv_uses_atomic_modeset(connector->dev))
+               armc = nouveau_conn_atom(connector->state);
+       else
+               armc = &nv_connector->properties_state;
 
        /* Init DVI-I specific properties. */
        if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
@@ -748,9 +762,9 @@ static int
 nouveau_connector_set_property(struct drm_connector *connector,
                               struct drm_property *property, uint64_t value)
 {
-       struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+       struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
        int ret;
 
index f43a8d6..de84fb4 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <nvif/notify.h>
 
+#include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
@@ -44,6 +45,60 @@ struct dcb_output;
 struct nouveau_backlight;
 #endif
 
+#define nouveau_conn_atom(p)                                                   \
+       container_of((p), struct nouveau_conn_atom, state)
+
+struct nouveau_conn_atom {
+       struct drm_connector_state state;
+
+       struct {
+               /* The enum values specifically defined here match nv50/gf119
+                * hw values, and the code relies on this.
+                */
+               enum {
+                       DITHERING_MODE_OFF = 0x00,
+                       DITHERING_MODE_ON = 0x01,
+                       DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
+                       DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
+                       DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
+                       DITHERING_MODE_AUTO
+               } mode;
+               enum {
+                       DITHERING_DEPTH_6BPC = 0x00,
+                       DITHERING_DEPTH_8BPC = 0x02,
+                       DITHERING_DEPTH_AUTO
+               } depth;
+       } dither;
+
+       struct {
+               int mode;       /* DRM_MODE_SCALE_* */
+               struct {
+                       enum {
+                               UNDERSCAN_OFF,
+                               UNDERSCAN_ON,
+                               UNDERSCAN_AUTO,
+                       } mode;
+                       u32 hborder;
+                       u32 vborder;
+               } underscan;
+               bool full;
+       } scaler;
+
+       struct {
+               int color_vibrance;
+               int vibrant_hue;
+       } procamp;
+
+       union {
+               struct {
+                       bool dither:1;
+                       bool scaler:1;
+                       bool procamp:1;
+               };
+               u8 mask;
+       } set;
+};
+
 struct nouveau_connector {
        struct drm_connector base;
        enum dcb_connector_type type;
@@ -63,6 +118,12 @@ struct nouveau_connector {
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
        struct nouveau_backlight *backlight;
 #endif
+       /*
+        * Our connector property code expects a nouveau_conn_atom struct
+        * even on pre-nv50 where we do not support atomic. This embedded
+        * version gets used in the non atomic modeset case.
+        */
+       struct nouveau_conn_atom properties_state;
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -121,61 +182,6 @@ extern int nouveau_ignorelid;
 extern int nouveau_duallink;
 extern int nouveau_hdmimhz;
 
-#include <drm/drm_crtc.h>
-#define nouveau_conn_atom(p)                                                   \
-       container_of((p), struct nouveau_conn_atom, state)
-
-struct nouveau_conn_atom {
-       struct drm_connector_state state;
-
-       struct {
-               /* The enum values specifically defined here match nv50/gf119
-                * hw values, and the code relies on this.
-                */
-               enum {
-                       DITHERING_MODE_OFF = 0x00,
-                       DITHERING_MODE_ON = 0x01,
-                       DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
-                       DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
-                       DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
-                       DITHERING_MODE_AUTO
-               } mode;
-               enum {
-                       DITHERING_DEPTH_6BPC = 0x00,
-                       DITHERING_DEPTH_8BPC = 0x02,
-                       DITHERING_DEPTH_AUTO
-               } depth;
-       } dither;
-
-       struct {
-               int mode;       /* DRM_MODE_SCALE_* */
-               struct {
-                       enum {
-                               UNDERSCAN_OFF,
-                               UNDERSCAN_ON,
-                               UNDERSCAN_AUTO,
-                       } mode;
-                       u32 hborder;
-                       u32 vborder;
-               } underscan;
-               bool full;
-       } scaler;
-
-       struct {
-               int color_vibrance;
-               int vibrant_hue;
-       } procamp;
-
-       union {
-               struct {
-                       bool dither:1;
-                       bool scaler:1;
-                       bool procamp:1;
-               };
-               u8 mask;
-       } set;
-};
-
 void nouveau_conn_attach_properties(struct drm_connector *);
 void nouveau_conn_reset(struct drm_connector *);
 struct drm_connector_state *
index 4c4e8a3..536ba93 100644 (file)
@@ -18,15 +18,18 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev);
 static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
                                   u32 flags)
 {
-       struct panfrost_device *pfdev = dev_get_drvdata(dev);
+       struct dev_pm_opp *opp;
        int err;
 
+       opp = devfreq_recommended_opp(dev, freq, flags);
+       if (IS_ERR(opp))
+               return PTR_ERR(opp);
+       dev_pm_opp_put(opp);
+
        err = dev_pm_opp_set_rate(dev, *freq);
        if (err)
                return err;
 
-       *freq = clk_get_rate(pfdev->clock);
-
        return 0;
 }
 
@@ -60,20 +63,10 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
        return 0;
 }
 
-static int panfrost_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
-{
-       struct panfrost_device *pfdev = platform_get_drvdata(to_platform_device(dev));
-
-       *freq = clk_get_rate(pfdev->clock);
-
-       return 0;
-}
-
 static struct devfreq_dev_profile panfrost_devfreq_profile = {
        .polling_ms = 50, /* ~3 frames */
        .target = panfrost_devfreq_target,
        .get_dev_status = panfrost_devfreq_get_dev_status,
-       .get_cur_freq = panfrost_devfreq_get_cur_freq,
 };
 
 int panfrost_devfreq_init(struct panfrost_device *pfdev)
index 9458dc6..f61364f 100644 (file)
@@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data,
        }
 
        /* Don't allow mmapping of heap objects as pages are not pinned. */
-       if (to_panfrost_bo(gem_obj)->is_heap)
-               return -EINVAL;
+       if (to_panfrost_bo(gem_obj)->is_heap) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        ret = drm_gem_create_mmap_offset(gem_obj);
        if (ret == 0)
                args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
-       drm_gem_object_put_unlocked(gem_obj);
 
+out:
+       drm_gem_object_put_unlocked(gem_obj);
        return ret;
 }
 
@@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
                return -ENOENT;
        }
 
+       mutex_lock(&pfdev->shrinker_lock);
        args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
 
        if (args->retained) {
                struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
 
-               mutex_lock(&pfdev->shrinker_lock);
-
                if (args->madv == PANFROST_MADV_DONTNEED)
-                       list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list);
+                       list_add_tail(&bo->base.madv_list,
+                                     &pfdev->shrinker_list);
                else if (args->madv == PANFROST_MADV_WILLNEED)
                        list_del_init(&bo->base.madv_list);
-
-               mutex_unlock(&pfdev->shrinker_lock);
        }
+       mutex_unlock(&pfdev->shrinker_lock);
 
        drm_gem_object_put_unlocked(gem_obj);
        return 0;
@@ -443,7 +445,7 @@ panfrost_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct panfrost_file_priv *panfrost_priv = file->driver_priv;
 
-       panfrost_perfcnt_close(panfrost_priv);
+       panfrost_perfcnt_close(file);
        panfrost_job_close(panfrost_priv);
 
        panfrost_mmu_pgtable_free(panfrost_priv);
index deca0c3..fd766b1 100644 (file)
@@ -19,6 +19,16 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
        struct panfrost_gem_object *bo = to_panfrost_bo(obj);
        struct panfrost_device *pfdev = obj->dev->dev_private;
 
+       /*
+        * Make sure the BO is no longer inserted in the shrinker list before
+        * taking care of the destruction itself. If we don't do that we have a
+        * race condition between this function and what's done in
+        * panfrost_gem_shrinker_scan().
+        */
+       mutex_lock(&pfdev->shrinker_lock);
+       list_del_init(&bo->base.madv_list);
+       mutex_unlock(&pfdev->shrinker_lock);
+
        if (bo->sgts) {
                int i;
                int n_sgt = bo->base.base.size / SZ_2M;
@@ -33,15 +43,10 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
                kfree(bo->sgts);
        }
 
-       mutex_lock(&pfdev->shrinker_lock);
-       if (!list_empty(&bo->base.madv_list))
-               list_del(&bo->base.madv_list);
-       mutex_unlock(&pfdev->shrinker_lock);
-
        drm_gem_shmem_free_object(obj);
 }
 
-static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
        int ret;
        size_t size = obj->size;
@@ -80,7 +85,7 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p
        return ret;
 }
 
-static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
+void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
        struct panfrost_gem_object *bo = to_panfrost_bo(obj);
        struct panfrost_file_priv *priv = file_priv->driver_priv;
index 5092081..4b17e73 100644 (file)
@@ -45,6 +45,10 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv,
                                u32 flags,
                                uint32_t *handle);
 
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv);
+void panfrost_gem_close(struct drm_gem_object *obj,
+                       struct drm_file *file_priv);
+
 void panfrost_gem_shrinker_init(struct drm_device *dev);
 void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
 
index 2dba192..2c04e85 100644 (file)
@@ -67,9 +67,10 @@ static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev)
 }
 
 static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
-                                         struct panfrost_file_priv *user,
+                                         struct drm_file *file_priv,
                                          unsigned int counterset)
 {
+       struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_gem_shmem_object *bo;
        u32 cfg;
@@ -91,14 +92,14 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
        perfcnt->bo = to_panfrost_bo(&bo->base);
 
        /* Map the perfcnt buf in the address space attached to file_priv. */
-       ret = panfrost_mmu_map(perfcnt->bo);
+       ret = panfrost_gem_open(&perfcnt->bo->base.base, file_priv);
        if (ret)
                goto err_put_bo;
 
        perfcnt->buf = drm_gem_shmem_vmap(&bo->base);
        if (IS_ERR(perfcnt->buf)) {
                ret = PTR_ERR(perfcnt->buf);
-               goto err_put_bo;
+               goto err_close_bo;
        }
 
        /*
@@ -157,14 +158,17 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
 
 err_vunmap:
        drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
+err_close_bo:
+       panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
 err_put_bo:
        drm_gem_object_put_unlocked(&bo->base);
        return ret;
 }
 
 static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
-                                          struct panfrost_file_priv *user)
+                                          struct drm_file *file_priv)
 {
+       struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
        if (user != perfcnt->user)
@@ -180,6 +184,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
        perfcnt->user = NULL;
        drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
        perfcnt->buf = NULL;
+       panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
        drm_gem_object_put_unlocked(&perfcnt->bo->base.base);
        perfcnt->bo = NULL;
        pm_runtime_mark_last_busy(pfdev->dev);
@@ -191,7 +196,6 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv)
 {
-       struct panfrost_file_priv *pfile = file_priv->driver_priv;
        struct panfrost_device *pfdev = dev->dev_private;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_panfrost_perfcnt_enable *req = data;
@@ -207,10 +211,10 @@ int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
 
        mutex_lock(&perfcnt->lock);
        if (req->enable)
-               ret = panfrost_perfcnt_enable_locked(pfdev, pfile,
+               ret = panfrost_perfcnt_enable_locked(pfdev, file_priv,
                                                     req->counterset);
        else
-               ret = panfrost_perfcnt_disable_locked(pfdev, pfile);
+               ret = panfrost_perfcnt_disable_locked(pfdev, file_priv);
        mutex_unlock(&perfcnt->lock);
 
        return ret;
@@ -248,15 +252,16 @@ out:
        return ret;
 }
 
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile)
+void panfrost_perfcnt_close(struct drm_file *file_priv)
 {
+       struct panfrost_file_priv *pfile = file_priv->driver_priv;
        struct panfrost_device *pfdev = pfile->pfdev;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
        pm_runtime_get_sync(pfdev->dev);
        mutex_lock(&perfcnt->lock);
        if (perfcnt->user == pfile)
-               panfrost_perfcnt_disable_locked(pfdev, pfile);
+               panfrost_perfcnt_disable_locked(pfdev, file_priv);
        mutex_unlock(&perfcnt->lock);
        pm_runtime_mark_last_busy(pfdev->dev);
        pm_runtime_put_autosuspend(pfdev->dev);
index 13b8fda..8bbcf5f 100644 (file)
@@ -9,7 +9,7 @@ void panfrost_perfcnt_sample_done(struct panfrost_device *pfdev);
 void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev);
 int panfrost_perfcnt_init(struct panfrost_device *pfdev);
 void panfrost_perfcnt_fini(struct panfrost_device *pfdev);
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile);
+void panfrost_perfcnt_close(struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data,
index 0dfd97b..ca232ec 100644 (file)
@@ -834,9 +834,6 @@ static irqreturn_t intel_th_irq(int irq, void *data)
                        ret |= d->irq(th->thdev[i]);
        }
 
-       if (ret == IRQ_NONE)
-               pr_warn_ratelimited("nobody cared for irq\n");
-
        return ret;
 }
 
@@ -887,6 +884,7 @@ intel_th_alloc(struct device *dev, struct intel_th_drvdata *drvdata,
 
                        if (th->irq == -1)
                                th->irq = devres[r].start;
+                       th->num_irqs++;
                        break;
                default:
                        dev_warn(dev, "Unknown resource type %lx\n",
@@ -940,6 +938,9 @@ void intel_th_free(struct intel_th *th)
 
        th->num_thdevs = 0;
 
+       for (i = 0; i < th->num_irqs; i++)
+               devm_free_irq(th->dev, th->irq + i, th);
+
        pm_runtime_get_sync(th->dev);
        pm_runtime_forbid(th->dev);
 
index 0df4800..6f4f548 100644 (file)
@@ -261,6 +261,7 @@ enum th_mmio_idx {
  * @num_thdevs:        number of devices in the @thdev array
  * @num_resources:     number of resources in the @resource array
  * @irq:       irq number
+ * @num_irqs:  number of IRQs is use
  * @id:                this Intel TH controller's device ID in the system
  * @major:     device node major for output devices
  */
@@ -277,6 +278,7 @@ struct intel_th {
        unsigned int            num_thdevs;
        unsigned int            num_resources;
        int                     irq;
+       int                     num_irqs;
 
        int                     id;
        int                     major;
index 6d240df..8e48c74 100644 (file)
@@ -1676,10 +1676,13 @@ static int intel_th_msc_init(struct msc *msc)
        return 0;
 }
 
-static void msc_win_switch(struct msc *msc)
+static int msc_win_switch(struct msc *msc)
 {
        struct msc_window *first;
 
+       if (list_empty(&msc->win_list))
+               return -EINVAL;
+
        first = list_first_entry(&msc->win_list, struct msc_window, entry);
 
        if (msc_is_last_win(msc->cur_win))
@@ -1691,6 +1694,8 @@ static void msc_win_switch(struct msc *msc)
        msc->base_addr = msc_win_base_dma(msc->cur_win);
 
        intel_th_trace_switch(msc->thdev);
+
+       return 0;
 }
 
 /**
@@ -2025,16 +2030,15 @@ win_switch_store(struct device *dev, struct device_attribute *attr,
        if (val != 1)
                return -EINVAL;
 
+       ret = -EINVAL;
        mutex_lock(&msc->buf_mutex);
        /*
         * Window switch can only happen in the "multi" mode.
         * If a external buffer is engaged, they have the full
         * control over window switching.
         */
-       if (msc->mode != MSC_MODE_MULTI || msc->mbuf)
-               ret = -ENOTSUPP;
-       else
-               msc_win_switch(msc);
+       if (msc->mode == MSC_MODE_MULTI && !msc->mbuf)
+               ret = msc_win_switch(msc);
        mutex_unlock(&msc->buf_mutex);
 
        return ret ? ret : size;
index ebf3e30..e9d90b5 100644 (file)
@@ -205,6 +205,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
        {
+               /* Comet Lake PCH-V */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
+       {
                /* Ice Lake NNPI */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
@@ -229,6 +234,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Elkhart Lake */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index 9333c86..9f8dcd3 100644 (file)
@@ -896,29 +896,6 @@ struct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address
 }
 EXPORT_SYMBOL_GPL(i2c_new_dummy_device);
 
-/**
- * i2c_new_dummy - return a new i2c device bound to a dummy driver
- * @adapter: the adapter managing the device
- * @address: seven bit address to be used
- * Context: can sleep
- *
- * This deprecated function has the same functionality as @i2c_new_dummy_device,
- * it just returns NULL instead of an ERR_PTR in case of an error for
- * compatibility with current I2C API. It will be removed once all users are
- * converted.
- *
- * This returns the new i2c client, which should be saved for later use with
- * i2c_unregister_device(); or NULL to indicate an error.
- */
-struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
-{
-       struct i2c_client *ret;
-
-       ret = i2c_new_dummy_device(adapter, address);
-       return IS_ERR(ret) ? NULL : ret;
-}
-EXPORT_SYMBOL_GPL(i2c_new_dummy);
-
 struct i2c_dummy_devres {
        struct i2c_client *client;
 };
index 7b83764..7320275 100644 (file)
@@ -992,6 +992,7 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
 #define ST_ACCEL_TRIGGER_OPS NULL
 #endif
 
+#ifdef CONFIG_ACPI
 static const struct iio_mount_matrix *
 get_mount_matrix(const struct iio_dev *indio_dev,
                 const struct iio_chan_spec *chan)
@@ -1012,7 +1013,6 @@ static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = {
 static int apply_acpi_orientation(struct iio_dev *indio_dev,
                                  struct iio_chan_spec *channels)
 {
-#ifdef CONFIG_ACPI
        struct st_sensor_data *adata = iio_priv(indio_dev);
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        struct acpi_device *adev;
@@ -1140,10 +1140,14 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
 out:
        kfree(buffer.pointer);
        return ret;
+}
 #else /* !CONFIG_ACPI */
+static int apply_acpi_orientation(struct iio_dev *indio_dev,
+                                 struct iio_chan_spec *channels)
+{
        return 0;
-#endif
 }
+#endif
 
 /*
  * st_accel_get_settings() - get sensor settings from device name
index edc6f1c..3f03abf 100644 (file)
@@ -39,6 +39,8 @@
 #define AD7124_STATUS_POR_FLAG_MSK     BIT(4)
 
 /* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_REF_EN_MSK     BIT(8)
+#define AD7124_ADC_CTRL_REF_EN(x)      FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x)
 #define AD7124_ADC_CTRL_PWR_MSK        GENMASK(7, 6)
 #define AD7124_ADC_CTRL_PWR(x)         FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
 #define AD7124_ADC_CTRL_MODE_MSK       GENMASK(5, 2)
@@ -424,7 +426,10 @@ static int ad7124_init_channel_vref(struct ad7124_state *st,
                break;
        case AD7124_INT_REF:
                st->channel_config[channel_number].vref_mv = 2500;
-               break;
+               st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK;
+               st->adc_control |= AD7124_ADC_CTRL_REF_EN(1);
+               return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL,
+                                     2, st->adc_control);
        default:
                dev_err(&st->sd.spi->dev, "Invalid reference %d\n", refsel);
                return -EINVAL;
index f5ba94c..e4683a6 100644 (file)
@@ -85,7 +85,7 @@ err_unlock:
 
 static int ad7606_read_samples(struct ad7606_state *st)
 {
-       unsigned int num = st->chip_info->num_channels;
+       unsigned int num = st->chip_info->num_channels - 1;
        u16 *data = st->data;
        int ret;
 
index 5c2b344..2c6f60e 100644 (file)
@@ -89,6 +89,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
                                   unsigned int channel)
 {
        int ret;
+       int i;
        int bits_per_word = ad7949_adc->resolution;
        int mask = GENMASK(ad7949_adc->resolution, 0);
        struct spi_message msg;
@@ -100,12 +101,23 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
                },
        };
 
-       ret = ad7949_spi_write_cfg(ad7949_adc,
-                                  channel << AD7949_OFFSET_CHANNEL_SEL,
-                                  AD7949_MASK_CHANNEL_SEL);
-       if (ret)
-               return ret;
+       /*
+        * 1: write CFG for sample N and read old data (sample N-2)
+        * 2: if CFG was not changed since sample N-1 then we'll get good data
+        *    at the next xfer, so we bail out now, otherwise we write something
+        *    and we read garbage (sample N-1 configuration).
+        */
+       for (i = 0; i < 2; i++) {
+               ret = ad7949_spi_write_cfg(ad7949_adc,
+                                          channel << AD7949_OFFSET_CHANNEL_SEL,
+                                          AD7949_MASK_CHANNEL_SEL);
+               if (ret)
+                       return ret;
+               if (channel == ad7949_adc->current_channel)
+                       break;
+       }
 
+       /* 3: write something and read actual data */
        ad7949_adc->buffer = 0;
        spi_message_init_with_transfers(&msg, tx, 1);
        ret = spi_sync(ad7949_adc->spi, &msg);
index 67d096f..c35a1be 100644 (file)
@@ -185,7 +185,7 @@ static int mrfld_adc_probe(struct platform_device *pdev)
        int irq;
        int ret;
 
-       indio_dev = devm_iio_device_alloc(dev, sizeof(*indio_dev));
+       indio_dev = devm_iio_device_alloc(dev, sizeof(struct mrfld_adc));
        if (!indio_dev)
                return -ENOMEM;
 
index e171db2..02834ca 100644 (file)
@@ -478,7 +478,13 @@ static int max1027_probe(struct spi_device *spi)
                st->trig->ops = &max1027_trigger_ops;
                st->trig->dev.parent = &spi->dev;
                iio_trigger_set_drvdata(st->trig, indio_dev);
-               iio_trigger_register(st->trig);
+               ret = devm_iio_trigger_register(&indio_dev->dev,
+                                               st->trig);
+               if (ret < 0) {
+                       dev_err(&indio_dev->dev,
+                               "Failed to register iio trigger\n");
+                       return ret;
+               }
 
                ret = devm_request_threaded_irq(&spi->dev, spi->irq,
                                                iio_trigger_generic_data_rdy_poll,
index da073d7..e480529 100644 (file)
 #define MAX9611_TEMP_SCALE_NUM         1000000
 #define MAX9611_TEMP_SCALE_DIV         2083
 
+/*
+ * Conversion time is 2 ms (typically) at Ta=25 degreeC
+ * No maximum value is known, so play it safe.
+ */
+#define MAX9611_CONV_TIME_US_RANGE     3000, 3300
+
 struct max9611_dev {
        struct device *dev;
        struct i2c_client *i2c_client;
@@ -236,11 +242,9 @@ static int max9611_read_single(struct max9611_dev *max9611,
                return ret;
        }
 
-       /*
-        * need a delay here to make register configuration
-        * stabilize. 1 msec at least, from empirical testing.
-        */
-       usleep_range(1000, 2000);
+       /* need a delay here to make register configuration stabilize. */
+
+       usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
        ret = i2c_smbus_read_word_swapped(max9611->i2c_client, reg_addr);
        if (ret < 0) {
@@ -507,7 +511,7 @@ static int max9611_init(struct max9611_dev *max9611)
                        MAX9611_REG_CTRL2, 0);
                return ret;
        }
-       usleep_range(1000, 2000);
+       usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
        return 0;
 }
index 963ff04..7ecd2ff 100644 (file)
@@ -229,7 +229,7 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev,
                        *val2 = 65536;
                        return IIO_VAL_FRACTIONAL;
                } else {
-                       *val = 100;
+                       *val = 100000;
                        *val2 = 65536;
                        return IIO_VAL_FRACTIONAL;
                }
index 45e77b3..0686e41 100644 (file)
@@ -117,6 +117,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6500_WHOAMI_VALUE,
@@ -124,6 +125,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6515_WHOAMI_VALUE,
@@ -131,6 +133,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6000_WHOAMI_VALUE,
@@ -138,6 +141,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9150_WHOAMI_VALUE,
@@ -145,6 +149,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9250_WHOAMI_VALUE,
@@ -152,6 +157,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9255_WHOAMI_VALUE,
@@ -159,6 +165,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_ICM20608_WHOAMI_VALUE,
@@ -166,6 +173,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
        },
        {
                .whoami = INV_ICM20602_WHOAMI_VALUE,
@@ -173,6 +181,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_icm20602,
                .config = &chip_config_6050,
                .fifo_size = 1008,
+               .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
        },
 };
 
@@ -481,12 +490,8 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
 
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       if (st->chip_type == INV_ICM20602)
-                               *val2 = INV_ICM20602_TEMP_SCALE;
-                       else
-                               *val2 = INV_MPU6050_TEMP_SCALE;
-
+                       *val = st->hw->temp.scale / 1000000;
+                       *val2 = st->hw->temp.scale % 1000000;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        return inv_mpu_magn_get_scale(st, chan, val, val2);
@@ -496,11 +501,7 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_OFFSET:
                switch (chan->type) {
                case IIO_TEMP:
-                       if (st->chip_type == INV_ICM20602)
-                               *val = INV_ICM20602_TEMP_OFFSET;
-                       else
-                               *val = INV_MPU6050_TEMP_OFFSET;
-
+                       *val = st->hw->temp.offset;
                        return IIO_VAL_INT;
                default:
                        return -EINVAL;
index f1fb7b6..b096e01 100644 (file)
@@ -107,6 +107,7 @@ struct inv_mpu6050_chip_config {
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
  *  @fifo_size:        size of the FIFO in bytes.
+ *  @temp:     offset and scale to apply to raw temperature.
  */
 struct inv_mpu6050_hw {
        u8 whoami;
@@ -114,6 +115,10 @@ struct inv_mpu6050_hw {
        const struct inv_mpu6050_reg_map *reg;
        const struct inv_mpu6050_chip_config *config;
        size_t fifo_size;
+       struct {
+               int offset;
+               int scale;
+       } temp;
 };
 
 /*
@@ -279,16 +284,19 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_REG_UP_TIME_MIN          5000
 #define INV_MPU6050_REG_UP_TIME_MAX          10000
 
-#define INV_MPU6050_TEMP_OFFSET                     12421
-#define INV_MPU6050_TEMP_SCALE               2941
+#define INV_MPU6050_TEMP_OFFSET                     12420
+#define INV_MPU6050_TEMP_SCALE               2941176
 #define INV_MPU6050_MAX_GYRO_FS_PARAM        3
 #define INV_MPU6050_MAX_ACCL_FS_PARAM        3
 #define INV_MPU6050_THREE_AXIS               3
 #define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT    3
 #define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT    3
 
-#define INV_ICM20602_TEMP_OFFSET            8170
-#define INV_ICM20602_TEMP_SCALE                     3060
+#define INV_MPU6500_TEMP_OFFSET              7011
+#define INV_MPU6500_TEMP_SCALE               2995178
+
+#define INV_ICM20608_TEMP_OFFSET            8170
+#define INV_ICM20608_TEMP_SCALE                     3059976
 
 /* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */
 #define INV_MPU6050_OUTPUT_DATA_SIZE         32
index c605b15..dc55d7d 100644 (file)
@@ -320,7 +320,6 @@ enum st_lsm6dsx_fifo_mode {
  * @odr: Output data rate of the sensor [Hz].
  * @watermark: Sensor watermark level.
  * @sip: Number of samples in a given pattern.
- * @decimator: FIFO decimation factor.
  * @ts_ref: Sensor timestamp reference for hw one.
  * @ext_info: Sensor settings if it is connected to i2c controller
  */
@@ -334,7 +333,6 @@ struct st_lsm6dsx_sensor {
 
        u16 watermark;
        u8 sip;
-       u8 decimator;
        s64 ts_ref;
 
        struct {
@@ -351,9 +349,9 @@ struct st_lsm6dsx_sensor {
  * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
  * @conf_lock: Mutex to prevent concurrent FIFO configuration update.
  * @page_lock: Mutex to prevent concurrent memory page configuration.
- * @fifo_mode: FIFO operating mode supported by the device.
  * @suspend_mask: Suspended sensor bitmask.
  * @enable_mask: Enabled sensor bitmask.
+ * @fifo_mask: Enabled hw FIFO bitmask.
  * @ts_gain: Hw timestamp rate after internal calibration.
  * @ts_sip: Total number of timestamp samples in a given pattern.
  * @sip: Total number of samples (acc/gyro/ts) in a given pattern.
@@ -373,9 +371,9 @@ struct st_lsm6dsx_hw {
        struct mutex conf_lock;
        struct mutex page_lock;
 
-       enum st_lsm6dsx_fifo_mode fifo_mode;
        u8 suspend_mask;
        u8 enable_mask;
+       u8 fifo_mask;
        s64 ts_gain;
        u8 ts_sip;
        u8 sip;
index d416990..cb536b8 100644 (file)
@@ -78,14 +78,20 @@ struct st_lsm6dsx_decimator_entry st_lsm6dsx_decimator_table[] = {
        { 32, 0x7 },
 };
 
-static int st_lsm6dsx_get_decimator_val(u8 val)
+static int
+st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr)
 {
        const int max_size = ARRAY_SIZE(st_lsm6dsx_decimator_table);
+       u32 decimator =  max_odr / sensor->odr;
        int i;
 
-       for (i = 0; i < max_size; i++)
-               if (st_lsm6dsx_decimator_table[i].decimator == val)
+       if (decimator > 1)
+               decimator = round_down(decimator, 2);
+
+       for (i = 0; i < max_size; i++) {
+               if (st_lsm6dsx_decimator_table[i].decimator == decimator)
                        break;
+       }
 
        return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val;
 }
@@ -111,6 +117,13 @@ static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,
        }
 }
 
+static u8 st_lsm6dsx_get_sip(struct st_lsm6dsx_sensor *sensor, u32 min_odr)
+{
+       u8 sip = sensor->odr / min_odr;
+
+       return sip > 1 ? round_down(sip, 2) : sip;
+}
+
 static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
 {
        const struct st_lsm6dsx_reg *ts_dec_reg;
@@ -131,12 +144,10 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
                sensor = iio_priv(hw->iio_devs[i]);
                /* update fifo decimators and sample in pattern */
                if (hw->enable_mask & BIT(sensor->id)) {
-                       sensor->sip = sensor->odr / min_odr;
-                       sensor->decimator = max_odr / sensor->odr;
-                       data = st_lsm6dsx_get_decimator_val(sensor->decimator);
+                       sensor->sip = st_lsm6dsx_get_sip(sensor, min_odr);
+                       data = st_lsm6dsx_get_decimator_val(sensor, max_odr);
                } else {
                        sensor->sip = 0;
-                       sensor->decimator = 0;
                        data = 0;
                }
                ts_sip = max_t(u16, ts_sip, sensor->sip);
@@ -176,17 +187,10 @@ int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
                             enum st_lsm6dsx_fifo_mode fifo_mode)
 {
        unsigned int data;
-       int err;
 
        data = FIELD_PREP(ST_LSM6DSX_FIFO_MODE_MASK, fifo_mode);
-       err = st_lsm6dsx_update_bits_locked(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
-                                           ST_LSM6DSX_FIFO_MODE_MASK, data);
-       if (err < 0)
-               return err;
-
-       hw->fifo_mode = fifo_mode;
-
-       return 0;
+       return st_lsm6dsx_update_bits_locked(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
+                                            ST_LSM6DSX_FIFO_MODE_MASK, data);
 }
 
 static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor,
@@ -608,11 +612,17 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
 int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
 {
        struct st_lsm6dsx_hw *hw = sensor->hw;
+       u8 fifo_mask;
        int err;
 
        mutex_lock(&hw->conf_lock);
 
-       if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) {
+       if (enable)
+               fifo_mask = hw->fifo_mask | BIT(sensor->id);
+       else
+               fifo_mask = hw->fifo_mask & ~BIT(sensor->id);
+
+       if (hw->fifo_mask) {
                err = st_lsm6dsx_flush_fifo(hw);
                if (err < 0)
                        goto out;
@@ -642,15 +652,19 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
        if (err < 0)
                goto out;
 
-       if (hw->enable_mask) {
+       if (fifo_mask) {
                /* reset hw ts counter */
                err = st_lsm6dsx_reset_hw_ts(hw);
                if (err < 0)
                        goto out;
 
                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+               if (err < 0)
+                       goto out;
        }
 
+       hw->fifo_mask = fifo_mask;
+
 out:
        mutex_unlock(&hw->conf_lock);
 
index 11b2c7b..a7d40c0 100644 (file)
@@ -1447,8 +1447,9 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
        return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
 }
 
-int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
-                                bool enable)
+static int
+__st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
+                              bool enable)
 {
        struct st_lsm6dsx_hw *hw = sensor->hw;
        u32 odr = enable ? sensor->odr : 0;
@@ -1466,6 +1467,26 @@ int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
        return 0;
 }
 
+static int
+st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable)
+{
+       struct st_lsm6dsx_hw *hw = sensor->hw;
+
+       if (sensor->id == ST_LSM6DSX_ID_GYRO || enable)
+               return 0;
+
+       return hw->enable_event;
+}
+
+int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
+                                bool enable)
+{
+       if (st_lsm6dsx_check_events(sensor, enable))
+               return 0;
+
+       return __st_lsm6dsx_sensor_set_enable(sensor, enable);
+}
+
 static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
                                   u8 addr, int *val)
 {
@@ -1661,7 +1682,7 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
        struct st_lsm6dsx_hw *hw = sensor->hw;
        u8 enable_event;
-       int err = 0;
+       int err;
 
        if (type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
@@ -1689,7 +1710,8 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
                return err;
 
        mutex_lock(&hw->conf_lock);
-       err = st_lsm6dsx_sensor_set_enable(sensor, state);
+       if (enable_event || !(hw->fifo_mask & BIT(sensor->id)))
+               err = __st_lsm6dsx_sensor_set_enable(sensor, state);
        mutex_unlock(&hw->conf_lock);
        if (err < 0)
                return err;
@@ -2300,7 +2322,7 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
                hw->suspend_mask |= BIT(sensor->id);
        }
 
-       if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS)
+       if (hw->fifo_mask)
                err = st_lsm6dsx_flush_fifo(hw);
 
        return err;
@@ -2336,7 +2358,7 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
                hw->suspend_mask &= ~BIT(sensor->id);
        }
 
-       if (hw->enable_mask)
+       if (hw->fifo_mask)
                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
 
        return err;
index ddf4702..d39c0d6 100644 (file)
@@ -444,8 +444,10 @@ static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new(
                        else
                                temp = __convert_to_raw(temp, resolution);
                } else {
-                       of_property_read_u32_index(np, propname, index,
-                                                  (u32 *)&temp);
+                       u32 t32;
+
+                       of_property_read_u32_index(np, propname, index, &t32);
+                       temp = t32;
                }
 
                for (j = 0; j < n_size; j++)
index 25f2b70..43a6f07 100644 (file)
@@ -4763,6 +4763,7 @@ err_ib:
 err:
        unregister_netdevice_notifier(&cma_nb);
        ib_sa_unregister_client(&sa_client);
+       unregister_pernet_subsys(&cma_pernet_operations);
 err_wq:
        destroy_workqueue(cma_wq);
        return ret;
index 8434ec0..2257d7f 100644 (file)
@@ -286,6 +286,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)
        struct rdma_counter *counter;
        int ret;
 
+       if (!qp->res.valid)
+               return 0;
+
        if (!rdma_is_port_valid(dev, port))
                return -EINVAL;
 
index f509c47..b7cb598 100644 (file)
@@ -238,28 +238,32 @@ void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry)
 EXPORT_SYMBOL(rdma_user_mmap_entry_remove);
 
 /**
- * rdma_user_mmap_entry_insert() - Insert an entry to the mmap_xa
+ * rdma_user_mmap_entry_insert_range() - Insert an entry to the mmap_xa
+ *                                      in a given range.
  *
  * @ucontext: associated user context.
  * @entry: the entry to insert into the mmap_xa
  * @length: length of the address that will be mmapped
+ * @min_pgoff: minimum pgoff to be returned
+ * @max_pgoff: maximum pgoff to be returned
  *
  * This function should be called by drivers that use the rdma_user_mmap
  * interface for implementing their mmap syscall A database of mmap offsets is
  * handled in the core and helper functions are provided to insert entries
  * into the database and extract entries when the user calls mmap with the
- * given offset.  The function allocates a unique page offset that should be
- * provided to user, the user will use the offset to retrieve information such
- * as address to be mapped and how.
+ * given offset. The function allocates a unique page offset in a given range
+ * that should be provided to user, the user will use the offset to retrieve
+ * information such as address to be mapped and how.
  *
  * Return: 0 on success and -ENOMEM on failure
  */
-int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
-                               struct rdma_user_mmap_entry *entry,
-                               size_t length)
+int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext,
+                                     struct rdma_user_mmap_entry *entry,
+                                     size_t length, u32 min_pgoff,
+                                     u32 max_pgoff)
 {
        struct ib_uverbs_file *ufile = ucontext->ufile;
-       XA_STATE(xas, &ucontext->mmap_xa, 0);
+       XA_STATE(xas, &ucontext->mmap_xa, min_pgoff);
        u32 xa_first, xa_last, npages;
        int err;
        u32 i;
@@ -285,7 +289,7 @@ int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
        entry->npages = npages;
        while (true) {
                /* First find an empty index */
-               xas_find_marked(&xas, U32_MAX, XA_FREE_MARK);
+               xas_find_marked(&xas, max_pgoff, XA_FREE_MARK);
                if (xas.xa_node == XAS_RESTART)
                        goto err_unlock;
 
@@ -332,4 +336,30 @@ err_unlock:
        mutex_unlock(&ufile->umap_lock);
        return -ENOMEM;
 }
+EXPORT_SYMBOL(rdma_user_mmap_entry_insert_range);
+
+/**
+ * rdma_user_mmap_entry_insert() - Insert an entry to the mmap_xa.
+ *
+ * @ucontext: associated user context.
+ * @entry: the entry to insert into the mmap_xa
+ * @length: length of the address that will be mmapped
+ *
+ * This function should be called by drivers that use the rdma_user_mmap
+ * interface for handling user mmapped addresses. The database is handled in
+ * the core and helper functions are provided to insert entries into the
+ * database and extract entries when the user calls mmap with the given offset.
+ * The function allocates a unique page offset that should be provided to user,
+ * the user will use the offset to retrieve information such as address to
+ * be mapped and how.
+ *
+ * Return: 0 on success and -ENOMEM on failure
+ */
+int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
+                               struct rdma_user_mmap_entry *entry,
+                               size_t length)
+{
+       return rdma_user_mmap_entry_insert_range(ucontext, entry, length, 0,
+                                                U32_MAX);
+}
 EXPORT_SYMBOL(rdma_user_mmap_entry_insert);
index c9d294c..50c2257 100644 (file)
@@ -145,7 +145,7 @@ static inline bool is_rdma_read_cap(struct efa_dev *dev)
 }
 
 #define field_avail(x, fld, sz) (offsetof(typeof(x), fld) + \
-                                FIELD_SIZEOF(typeof(x), fld) <= (sz))
+                                sizeof_field(typeof(x), fld) <= (sz))
 
 #define is_reserved_cleared(reserved) \
        !memchr_inv(reserved, 0, sizeof(reserved))
index 5774dfc..a515256 100644 (file)
@@ -848,7 +848,7 @@ static const struct rhashtable_params sdma_rht_params = {
        .nelem_hint = NR_CPUS_HINT,
        .head_offset = offsetof(struct sdma_rht_node, node),
        .key_offset = offsetof(struct sdma_rht_node, cpu_id),
-       .key_len = FIELD_SIZEOF(struct sdma_rht_node, cpu_id),
+       .key_len = sizeof_field(struct sdma_rht_node, cpu_id),
        .max_size = NR_CPUS,
        .min_size = 8,
        .automatic_shrinking = true,
index b0e9bf7..d36e3e1 100644 (file)
@@ -107,9 +107,9 @@ enum {
        HFI1_HAS_GRH = (1 << 0),
 };
 
-#define LRH_16B_BYTES (FIELD_SIZEOF(struct hfi1_16b_header, lrh))
+#define LRH_16B_BYTES (sizeof_field(struct hfi1_16b_header, lrh))
 #define LRH_16B_DWORDS (LRH_16B_BYTES / sizeof(u32))
-#define LRH_9B_BYTES (FIELD_SIZEOF(struct ib_header, lrh))
+#define LRH_9B_BYTES (sizeof_field(struct ib_header, lrh))
 #define LRH_9B_DWORDS (LRH_9B_BYTES / sizeof(u32))
 
 /* 24Bits for qpn, upper 8Bits reserved */
index 0b5dc1d..34055cb 100644 (file)
@@ -3018,16 +3018,17 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
        ibdev->ib_active = false;
        flush_workqueue(wq);
 
-       mlx4_ib_close_sriov(ibdev);
-       mlx4_ib_mad_cleanup(ibdev);
-       ib_unregister_device(&ibdev->ib_dev);
-       mlx4_ib_diag_cleanup(ibdev);
        if (ibdev->iboe.nb.notifier_call) {
                if (unregister_netdevice_notifier(&ibdev->iboe.nb))
                        pr_warn("failure unregistering notifier\n");
                ibdev->iboe.nb.notifier_call = NULL;
        }
 
+       mlx4_ib_close_sriov(ibdev);
+       mlx4_ib_mad_cleanup(ibdev);
+       ib_unregister_device(&ibdev->ib_dev);
+       mlx4_ib_diag_cleanup(ibdev);
+
        mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
                              ibdev->steer_qpn_count);
        kfree(ibdev->ib_uc_qpns_bitmap);
index 4937947..4c26492 100644 (file)
@@ -157,7 +157,7 @@ int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
        return -ENOMEM;
 }
 
-int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
+void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
 {
        struct mlx5_core_dev *dev = dm->dev;
        u64 hw_start_addr = MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr);
@@ -175,15 +175,13 @@ int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
        MLX5_SET(dealloc_memic_in, in, memic_size, length);
 
        err =  mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (err)
+               return;
 
-       if (!err) {
-               spin_lock(&dm->lock);
-               bitmap_clear(dm->memic_alloc_pages,
-                            start_page_idx, num_pages);
-               spin_unlock(&dm->lock);
-       }
-
-       return err;
+       spin_lock(&dm->lock);
+       bitmap_clear(dm->memic_alloc_pages,
+                    start_page_idx, num_pages);
+       spin_unlock(&dm->lock);
 }
 
 int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out)
index 169cab4..945ebce 100644 (file)
@@ -46,7 +46,7 @@ int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev,
                                void *in, int in_size);
 int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
                         u64 length, u32 alignment);
-int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
+void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
 void mlx5_cmd_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn, u16 uid);
 void mlx5_cmd_destroy_tir(struct mlx5_core_dev *dev, u32 tirn, u16 uid);
 void mlx5_cmd_destroy_tis(struct mlx5_core_dev *dev, u32 tisn, u16 uid);
index 5110035..997cbfe 100644 (file)
@@ -2074,6 +2074,24 @@ static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,
                              virt_to_page(dev->mdev->clock_info));
 }
 
+static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
+{
+       struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
+       struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
+       struct mlx5_ib_dm *mdm;
+
+       switch (mentry->mmap_flag) {
+       case MLX5_IB_MMAP_TYPE_MEMIC:
+               mdm = container_of(mentry, struct mlx5_ib_dm, mentry);
+               mlx5_cmd_dealloc_memic(&dev->dm, mdm->dev_addr,
+                                      mdm->size);
+               kfree(mdm);
+               break;
+       default:
+               WARN_ON(true);
+       }
+}
+
 static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
                    struct vm_area_struct *vma,
                    struct mlx5_ib_ucontext *context)
@@ -2186,26 +2204,55 @@ free_bfreg:
        return err;
 }
 
-static int dm_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+static int add_dm_mmap_entry(struct ib_ucontext *context,
+                            struct mlx5_ib_dm *mdm,
+                            u64 address)
+{
+       mdm->mentry.mmap_flag = MLX5_IB_MMAP_TYPE_MEMIC;
+       mdm->mentry.address = address;
+       return rdma_user_mmap_entry_insert_range(
+                       context, &mdm->mentry.rdma_entry,
+                       mdm->size,
+                       MLX5_IB_MMAP_DEVICE_MEM << 16,
+                       (MLX5_IB_MMAP_DEVICE_MEM << 16) + (1UL << 16) - 1);
+}
+
+static unsigned long mlx5_vma_to_pgoff(struct vm_area_struct *vma)
+{
+       unsigned long idx;
+       u8 command;
+
+       command = get_command(vma->vm_pgoff);
+       idx = get_extended_index(vma->vm_pgoff);
+
+       return (command << 16 | idx);
+}
+
+static int mlx5_ib_mmap_offset(struct mlx5_ib_dev *dev,
+                              struct vm_area_struct *vma,
+                              struct ib_ucontext *ucontext)
 {
-       struct mlx5_ib_ucontext *mctx = to_mucontext(context);
-       struct mlx5_ib_dev *dev = to_mdev(context->device);
-       u16 page_idx = get_extended_index(vma->vm_pgoff);
-       size_t map_size = vma->vm_end - vma->vm_start;
-       u32 npages = map_size >> PAGE_SHIFT;
+       struct mlx5_user_mmap_entry *mentry;
+       struct rdma_user_mmap_entry *entry;
+       unsigned long pgoff;
+       pgprot_t prot;
        phys_addr_t pfn;
+       int ret;
 
-       if (find_next_zero_bit(mctx->dm_pages, page_idx + npages, page_idx) !=
-           page_idx + npages)
+       pgoff = mlx5_vma_to_pgoff(vma);
+       entry = rdma_user_mmap_entry_get_pgoff(ucontext, pgoff);
+       if (!entry)
                return -EINVAL;
 
-       pfn = ((dev->mdev->bar_addr +
-             MLX5_CAP64_DEV_MEM(dev->mdev, memic_bar_start_addr)) >>
-             PAGE_SHIFT) +
-             page_idx;
-       return rdma_user_mmap_io(context, vma, pfn, map_size,
-                                pgprot_writecombine(vma->vm_page_prot),
-                                NULL);
+       mentry = to_mmmap(entry);
+       pfn = (mentry->address >> PAGE_SHIFT);
+       prot = pgprot_writecombine(vma->vm_page_prot);
+       ret = rdma_user_mmap_io(ucontext, vma, pfn,
+                               entry->npages * PAGE_SIZE,
+                               prot,
+                               entry);
+       rdma_user_mmap_entry_put(&mentry->rdma_entry);
+       return ret;
 }
 
 static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
@@ -2248,11 +2295,8 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
        case MLX5_IB_MMAP_CLOCK_INFO:
                return mlx5_ib_mmap_clock_info_page(dev, vma, context);
 
-       case MLX5_IB_MMAP_DEVICE_MEM:
-               return dm_mmap(ibcontext, vma);
-
        default:
-               return -EINVAL;
+               return mlx5_ib_mmap_offset(dev, vma, ibcontext);
        }
 
        return 0;
@@ -2288,8 +2332,9 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
 {
        struct mlx5_dm *dm_db = &to_mdev(ctx->device)->dm;
        u64 start_offset;
-       u32 page_idx;
+       u16 page_idx;
        int err;
+       u64 address;
 
        dm->size = roundup(attr->length, MLX5_MEMIC_BASE_SIZE);
 
@@ -2298,28 +2343,30 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
        if (err)
                return err;
 
-       page_idx = (dm->dev_addr - pci_resource_start(dm_db->dev->pdev, 0) -
-                   MLX5_CAP64_DEV_MEM(dm_db->dev, memic_bar_start_addr)) >>
-                   PAGE_SHIFT;
+       address = dm->dev_addr & PAGE_MASK;
+       err = add_dm_mmap_entry(ctx, dm, address);
+       if (err)
+               goto err_dealloc;
 
+       page_idx = dm->mentry.rdma_entry.start_pgoff & 0xFFFF;
        err = uverbs_copy_to(attrs,
                             MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
-                            &page_idx, sizeof(page_idx));
+                            &page_idx,
+                            sizeof(page_idx));
        if (err)
-               goto err_dealloc;
+               goto err_copy;
 
        start_offset = dm->dev_addr & ~PAGE_MASK;
        err = uverbs_copy_to(attrs,
                             MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
                             &start_offset, sizeof(start_offset));
        if (err)
-               goto err_dealloc;
-
-       bitmap_set(to_mucontext(ctx)->dm_pages, page_idx,
-                  DIV_ROUND_UP(dm->size, PAGE_SIZE));
+               goto err_copy;
 
        return 0;
 
+err_copy:
+       rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
 err_dealloc:
        mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
 
@@ -2423,23 +2470,13 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
        struct mlx5_ib_ucontext *ctx = rdma_udata_to_drv_context(
                &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
        struct mlx5_core_dev *dev = to_mdev(ibdm->device)->mdev;
-       struct mlx5_dm *dm_db = &to_mdev(ibdm->device)->dm;
        struct mlx5_ib_dm *dm = to_mdm(ibdm);
-       u32 page_idx;
        int ret;
 
        switch (dm->type) {
        case MLX5_IB_UAPI_DM_TYPE_MEMIC:
-               ret = mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
-               if (ret)
-                       return ret;
-
-               page_idx = (dm->dev_addr - pci_resource_start(dev->pdev, 0) -
-                           MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr)) >>
-                           PAGE_SHIFT;
-               bitmap_clear(ctx->dm_pages, page_idx,
-                            DIV_ROUND_UP(dm->size, PAGE_SIZE));
-               break;
+               rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
+               return 0;
        case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
                ret = mlx5_dm_sw_icm_dealloc(dev, MLX5_SW_ICM_TYPE_STEERING,
                                             dm->size, ctx->devx_uid, dm->dev_addr,
@@ -3544,10 +3581,6 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
        }
 
        INIT_LIST_HEAD(&handler->list);
-       if (dst) {
-               memcpy(&dest_arr[0], dst, sizeof(*dst));
-               dest_num++;
-       }
 
        for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
                err = parse_flow_attr(dev->mdev, spec,
@@ -3560,6 +3593,11 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
                ib_flow += ((union ib_flow_spec *)ib_flow)->size;
        }
 
+       if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) {
+               memcpy(&dest_arr[0], dst, sizeof(*dst));
+               dest_num++;
+       }
+
        if (!flow_is_multicast_only(flow_attr))
                set_underlay_qp(dev, spec, underlay_qpn);
 
@@ -3600,10 +3638,8 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
        }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
-               if (!(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) {
+               if (!dest_num)
                        rule_dst = NULL;
-                       dest_num = 0;
-               }
        } else {
                if (is_egress)
                        flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
@@ -6236,6 +6272,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
        .map_mr_sg = mlx5_ib_map_mr_sg,
        .map_mr_sg_pi = mlx5_ib_map_mr_sg_pi,
        .mmap = mlx5_ib_mmap,
+       .mmap_free = mlx5_ib_mmap_free,
        .modify_cq = mlx5_ib_modify_cq,
        .modify_device = mlx5_ib_modify_device,
        .modify_port = mlx5_ib_modify_port,
index 5986953..b06f32f 100644 (file)
@@ -118,6 +118,10 @@ enum {
        MLX5_MEMIC_BASE_SIZE    = 1 << MLX5_MEMIC_BASE_ALIGN,
 };
 
+enum mlx5_ib_mmap_type {
+       MLX5_IB_MMAP_TYPE_MEMIC = 1,
+};
+
 #define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev)                                        \
        (MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity))
 #define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev))
@@ -135,7 +139,6 @@ struct mlx5_ib_ucontext {
        u32                     tdn;
 
        u64                     lib_caps;
-       DECLARE_BITMAP(dm_pages, MLX5_MAX_MEMIC_PAGES);
        u16                     devx_uid;
        /* For RoCE LAG TX affinity */
        atomic_t                tx_port_affinity;
@@ -556,6 +559,12 @@ enum mlx5_ib_mtt_access_flags {
        MLX5_IB_MTT_WRITE = (1 << 1),
 };
 
+struct mlx5_user_mmap_entry {
+       struct rdma_user_mmap_entry rdma_entry;
+       u8 mmap_flag;
+       u64 address;
+};
+
 struct mlx5_ib_dm {
        struct ib_dm            ibdm;
        phys_addr_t             dev_addr;
@@ -567,6 +576,7 @@ struct mlx5_ib_dm {
                } icm_dm;
                /* other dm types specific params should be added here */
        };
+       struct mlx5_user_mmap_entry mentry;
 };
 
 #define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
@@ -1101,6 +1111,13 @@ to_mflow_act(struct ib_flow_action *ibact)
        return container_of(ibact, struct mlx5_ib_flow_action, ib_action);
 }
 
+static inline struct mlx5_user_mmap_entry *
+to_mmmap(struct rdma_user_mmap_entry *rdma_entry)
+{
+       return container_of(rdma_entry,
+               struct mlx5_user_mmap_entry, rdma_entry);
+}
+
 int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context,
                        struct ib_udata *udata, unsigned long virt,
                        struct mlx5_db *db);
index f9a492e..831ad57 100644 (file)
@@ -389,7 +389,7 @@ void rxe_rcv(struct sk_buff *skb)
 
        calc_icrc = rxe_icrc_hdr(pkt, skb);
        calc_icrc = rxe_crc32(rxe, calc_icrc, (u8 *)payload_addr(pkt),
-                             payload_size(pkt));
+                             payload_size(pkt) + bth_pad(pkt));
        calc_icrc = (__force u32)cpu_to_be32(~calc_icrc);
        if (unlikely(calc_icrc != pack_icrc)) {
                if (skb->protocol == htons(ETH_P_IPV6))
index c5d9b55..e503117 100644 (file)
@@ -500,6 +500,12 @@ static int fill_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
                        if (err)
                                return err;
                }
+               if (bth_pad(pkt)) {
+                       u8 *pad = payload_addr(pkt) + paylen;
+
+                       memset(pad, 0, bth_pad(pkt));
+                       crc = rxe_crc32(rxe, crc, pad, bth_pad(pkt));
+               }
        }
        p = payload_addr(pkt) + paylen + bth_pad(pkt);
 
index 1cbfbd9..c4a8195 100644 (file)
@@ -732,6 +732,13 @@ static enum resp_states read_reply(struct rxe_qp *qp,
        if (err)
                pr_err("Failed copying memory\n");
 
+       if (bth_pad(&ack_pkt)) {
+               struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+               u8 *pad = payload_addr(&ack_pkt) + payload;
+
+               memset(pad, 0, bth_pad(&ack_pkt));
+               icrc = rxe_crc32(rxe, icrc, pad, bth_pad(&ack_pkt));
+       }
        p = payload_addr(&ack_pkt) + payload + bth_pad(&ack_pkt);
        *p = ~icrc;
 
index 62390e9..8ad7da9 100644 (file)
@@ -63,7 +63,7 @@ struct vnic_stats {
        };
 };
 
-#define VNIC_STAT(m)            { FIELD_SIZEOF(struct opa_vnic_stats, m),   \
+#define VNIC_STAT(m)            { sizeof_field(struct opa_vnic_stats, m),   \
                                  offsetof(struct opa_vnic_stats, m) }
 
 static struct vnic_stats vnic_gstrings_stats[] = {
index c49afbe..2f9304d 100644 (file)
@@ -6,13 +6,13 @@ config INTERCONNECT_QCOM
          Support for Qualcomm's Network-on-Chip interconnect hardware.
 
 config INTERCONNECT_QCOM_MSM8974
-       tristate "Qualcomm MSM8974 interconnect driver"
-       depends on INTERCONNECT_QCOM
-       depends on QCOM_SMD_RPM
-       select INTERCONNECT_QCOM_SMD_RPM
-       help
-         This is a driver for the Qualcomm Network-on-Chip on msm8974-based
-         platforms.
+       tristate "Qualcomm MSM8974 interconnect driver"
+       depends on INTERCONNECT_QCOM
+       depends on QCOM_SMD_RPM
+       select INTERCONNECT_QCOM_SMD_RPM
+       help
+        This is a driver for the Qualcomm Network-on-Chip on msm8974-based
+        platforms.
 
 config INTERCONNECT_QCOM_QCS404
        tristate "Qualcomm QCS404 interconnect driver"
index ce599a0..bf8bd1a 100644 (file)
@@ -652,7 +652,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct icc_onecell_data *data;
        struct icc_provider *provider;
-       struct icc_node *node;
+       struct icc_node *node, *tmp;
        size_t num_nodes, i;
        int ret;
 
@@ -732,7 +732,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        return 0;
 
 err_del_icc:
-       list_for_each_entry(node, &provider->nodes, node_list) {
+       list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
                icc_node_del(node);
                icc_node_destroy(node->id);
        }
@@ -748,9 +748,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
 {
        struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index b4966d8..8e0735a 100644 (file)
@@ -414,7 +414,7 @@ static int qnoc_probe(struct platform_device *pdev)
        struct icc_provider *provider;
        struct qcom_icc_node **qnodes;
        struct qcom_icc_provider *qp;
-       struct icc_node *node;
+       struct icc_node *node, *tmp;
        size_t num_nodes, i;
        int ret;
 
@@ -494,7 +494,7 @@ static int qnoc_probe(struct platform_device *pdev)
 
        return 0;
 err:
-       list_for_each_entry(node, &provider->nodes, node_list) {
+       list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
                icc_node_del(node);
                icc_node_destroy(node->id);
        }
@@ -508,9 +508,9 @@ static int qnoc_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index 502a6c2..387267e 100644 (file)
@@ -868,9 +868,9 @@ static int qnoc_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index 0cc702a..c363294 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/iova.h>
 #include <linux/irq.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/vmalloc.h>
@@ -44,7 +45,6 @@ struct iommu_dma_cookie {
                dma_addr_t              msi_iova;
        };
        struct list_head                msi_page_list;
-       spinlock_t                      msi_lock;
 
        /* Domain for flush queue callback; NULL if flush queue not in use */
        struct iommu_domain             *fq_domain;
@@ -63,7 +63,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
 
        cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
        if (cookie) {
-               spin_lock_init(&cookie->msi_lock);
                INIT_LIST_HEAD(&cookie->msi_page_list);
                cookie->type = type;
        }
@@ -399,7 +398,7 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent,
 }
 
 static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
-               size_t size, dma_addr_t dma_limit, struct device *dev)
+               size_t size, u64 dma_limit, struct device *dev)
 {
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
        struct iova_domain *iovad = &cookie->iovad;
@@ -424,7 +423,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
        dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
 
        if (domain->geometry.force_aperture)
-               dma_limit = min(dma_limit, domain->geometry.aperture_end);
+               dma_limit = min(dma_limit, (u64)domain->geometry.aperture_end);
 
        /* Try to get PCI devices a SAC address */
        if (dma_limit > DMA_BIT_MASK(32) && dev_is_pci(dev))
@@ -477,7 +476,7 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
 }
 
 static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
-               size_t size, int prot, dma_addr_t dma_mask)
+               size_t size, int prot, u64 dma_mask)
 {
        struct iommu_domain *domain = iommu_get_dma_domain(dev);
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
@@ -1176,7 +1175,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
                if (msi_page->phys == msi_addr)
                        return msi_page;
 
-       msi_page = kzalloc(sizeof(*msi_page), GFP_ATOMIC);
+       msi_page = kzalloc(sizeof(*msi_page), GFP_KERNEL);
        if (!msi_page)
                return NULL;
 
@@ -1206,7 +1205,7 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
        struct iommu_dma_cookie *cookie;
        struct iommu_dma_msi_page *msi_page;
-       unsigned long flags;
+       static DEFINE_MUTEX(msi_prepare_lock); /* see below */
 
        if (!domain || !domain->iova_cookie) {
                desc->iommu_cookie = NULL;
@@ -1216,13 +1215,13 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
        cookie = domain->iova_cookie;
 
        /*
-        * We disable IRQs to rule out a possible inversion against
-        * irq_desc_lock if, say, someone tries to retarget the affinity
-        * of an MSI from within an IPI handler.
+        * In fact the whole prepare operation should already be serialised by
+        * irq_domain_mutex further up the callchain, but that's pretty subtle
+        * on its own, so consider this locking as failsafe documentation...
         */
-       spin_lock_irqsave(&cookie->msi_lock, flags);
+       mutex_lock(&msi_prepare_lock);
        msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
-       spin_unlock_irqrestore(&cookie->msi_lock, flags);
+       mutex_unlock(&msi_prepare_lock);
 
        msi_desc_set_iommu_cookie(desc, msi_page);
 
index 0c8d81f..4296661 100644 (file)
@@ -5478,9 +5478,6 @@ static int intel_iommu_map(struct iommu_domain *domain,
        int prot = 0;
        int ret;
 
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return -EINVAL;
-
        if (iommu_prot & IOMMU_READ)
                prot |= DMA_PTE_READ;
        if (iommu_prot & IOMMU_WRITE)
@@ -5523,8 +5520,6 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
        /* Cope with horrid API which requires us to unmap more than the
           size argument if it happens to be a large-page mapping. */
        BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return 0;
 
        if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
                size = VTD_PAGE_SIZE << level_to_offset_bits(level);
@@ -5556,9 +5551,6 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
        int level = 0;
        u64 phys = 0;
 
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return 0;
-
        pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
        if (pte)
                phys = dma_pte_addr(pte);
@@ -5736,8 +5728,8 @@ static void intel_iommu_get_resv_regions(struct device *device,
                struct pci_dev *pdev = to_pci_dev(device);
 
                if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
-                       reg = iommu_alloc_resv_region(0, 1UL << 24, 0,
-                                                     IOMMU_RESV_DIRECT);
+                       reg = iommu_alloc_resv_region(0, 1UL << 24, prot,
+                                                  IOMMU_RESV_DIRECT_RELAXABLE);
                        if (reg)
                                list_add_tail(&reg->list, head);
                }
index 9b15913..dca88f9 100644 (file)
@@ -104,11 +104,7 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
 {
        struct qi_desc desc;
 
-       /*
-        * Do PASID granu IOTLB invalidation if page selective capability is
-        * not available.
-        */
-       if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+       if (pages == -1) {
                desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
                        QI_EIOTLB_DID(sdev->did) |
                        QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
index db7bfd4..fdd4075 100644 (file)
@@ -312,8 +312,8 @@ int iommu_insert_resv_region(struct iommu_resv_region *new,
        list_for_each_entry_safe(iter, tmp, regions, list) {
                phys_addr_t top_end, iter_end = iter->start + iter->length - 1;
 
-               /* no merge needed on elements of different types than @nr */
-               if (iter->type != nr->type) {
+               /* no merge needed on elements of different types than @new */
+               if (iter->type != new->type) {
                        list_move_tail(&iter->list, &stack);
                        continue;
                }
@@ -2282,13 +2282,13 @@ request_default_domain_for_dev(struct device *dev, unsigned long type)
                goto out;
        }
 
-       iommu_group_create_direct_mappings(group, dev);
-
        /* Make the domain the default for this group */
        if (group->default_domain)
                iommu_domain_free(group->default_domain);
        group->default_domain = domain;
 
+       iommu_group_create_direct_mappings(group, dev);
+
        dev_info(dev, "Using iommu %s mapping\n",
                 type == IOMMU_DOMAIN_DMA ? "dma" : "direct");
 
index 41c605b..c7a914b 100644 (file)
@@ -233,7 +233,7 @@ static DEFINE_MUTEX(iova_cache_mutex);
 
 struct iova *alloc_iova_mem(void)
 {
-       return kmem_cache_alloc(iova_cache, GFP_ATOMIC);
+       return kmem_cache_zalloc(iova_cache, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(alloc_iova_mem);
 
index 08c552e..c05b121 100644 (file)
@@ -67,23 +67,34 @@ struct superblock_disk {
  * To save constantly doing look ups on disk we keep an in core copy of the
  * on-disk bitmap, the region_map.
  *
- * To further reduce metadata I/O overhead we use a second bitmap, the dmap
- * (dirty bitmap), which tracks the dirty words, i.e. longs, of the region_map.
+ * In order to track which regions are hydrated during a metadata transaction,
+ * we use a second set of bitmaps, the dmap (dirty bitmap), which includes two
+ * bitmaps, namely dirty_regions and dirty_words. The dirty_regions bitmap
+ * tracks the regions that got hydrated during the current metadata
+ * transaction. The dirty_words bitmap tracks the dirty words, i.e. longs, of
+ * the dirty_regions bitmap.
+ *
+ * This allows us to precisely track the regions that were hydrated during the
+ * current metadata transaction and update the metadata accordingly, when we
+ * commit the current transaction. This is important because dm-clone should
+ * only commit the metadata of regions that were properly flushed to the
+ * destination device beforehand. Otherwise, in case of a crash, we could end
+ * up with a corrupted dm-clone device.
  *
  * When a region finishes hydrating dm-clone calls
  * dm_clone_set_region_hydrated(), or for discard requests
  * dm_clone_cond_set_range(), which sets the corresponding bits in region_map
  * and dmap.
  *
- * During a metadata commit we scan the dmap for dirty region_map words (longs)
- * and update accordingly the on-disk metadata. Thus, we don't have to flush to
- * disk the whole region_map. We can just flush the dirty region_map words.
+ * During a metadata commit we scan dmap->dirty_words and dmap->dirty_regions
+ * and update the on-disk metadata accordingly. Thus, we don't have to flush to
+ * disk the whole region_map. We can just flush the dirty region_map bits.
  *
- * We use a dirty bitmap, which is smaller than the original region_map, to
- * reduce the amount of memory accesses during a metadata commit. As dm-bitset
- * accesses the on-disk bitmap in 64-bit word granularity, there is no
- * significant benefit in tracking the dirty region_map bits with a smaller
- * granularity.
+ * We use the helper dmap->dirty_words bitmap, which is smaller than the
+ * original region_map, to reduce the amount of memory accesses during a
+ * metadata commit. Moreover, as dm-bitset also accesses the on-disk bitmap in
+ * 64-bit word granularity, the dirty_words bitmap helps us avoid useless disk
+ * accesses.
  *
  * We could update directly the on-disk bitmap, when dm-clone calls either
  * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), buts this
@@ -92,12 +103,13 @@ struct superblock_disk {
  * e.g., in a hooked overwrite bio's completion routine, and further reduce the
  * I/O completion latency.
  *
- * We maintain two dirty bitmaps. During a metadata commit we atomically swap
- * the currently used dmap with the unused one. This allows the metadata update
- * functions to run concurrently with an ongoing commit.
+ * We maintain two dirty bitmap sets. During a metadata commit we atomically
+ * swap the currently used dmap with the unused one. This allows the metadata
+ * update functions to run concurrently with an ongoing commit.
  */
 struct dirty_map {
        unsigned long *dirty_words;
+       unsigned long *dirty_regions;
        unsigned int changed;
 };
 
@@ -115,6 +127,9 @@ struct dm_clone_metadata {
        struct dirty_map dmap[2];
        struct dirty_map *current_dmap;
 
+       /* Protected by lock */
+       struct dirty_map *committing_dmap;
+
        /*
         * In core copy of the on-disk bitmap to save constantly doing look ups
         * on disk.
@@ -461,34 +476,53 @@ static size_t bitmap_size(unsigned long nr_bits)
        return BITS_TO_LONGS(nr_bits) * sizeof(long);
 }
 
-static int dirty_map_init(struct dm_clone_metadata *cmd)
+static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
+                           unsigned long nr_regions)
 {
-       cmd->dmap[0].changed = 0;
-       cmd->dmap[0].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+       dmap->changed = 0;
 
-       if (!cmd->dmap[0].dirty_words) {
-               DMERR("Failed to allocate dirty bitmap");
+       dmap->dirty_words = kvzalloc(bitmap_size(nr_words), GFP_KERNEL);
+       if (!dmap->dirty_words)
+               return -ENOMEM;
+
+       dmap->dirty_regions = kvzalloc(bitmap_size(nr_regions), GFP_KERNEL);
+       if (!dmap->dirty_regions) {
+               kvfree(dmap->dirty_words);
                return -ENOMEM;
        }
 
-       cmd->dmap[1].changed = 0;
-       cmd->dmap[1].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+       return 0;
+}
+
+static void __dirty_map_exit(struct dirty_map *dmap)
+{
+       kvfree(dmap->dirty_words);
+       kvfree(dmap->dirty_regions);
+}
+
+static int dirty_map_init(struct dm_clone_metadata *cmd)
+{
+       if (__dirty_map_init(&cmd->dmap[0], cmd->nr_words, cmd->nr_regions)) {
+               DMERR("Failed to allocate dirty bitmap");
+               return -ENOMEM;
+       }
 
-       if (!cmd->dmap[1].dirty_words) {
+       if (__dirty_map_init(&cmd->dmap[1], cmd->nr_words, cmd->nr_regions)) {
                DMERR("Failed to allocate dirty bitmap");
-               kvfree(cmd->dmap[0].dirty_words);
+               __dirty_map_exit(&cmd->dmap[0]);
                return -ENOMEM;
        }
 
        cmd->current_dmap = &cmd->dmap[0];
+       cmd->committing_dmap = NULL;
 
        return 0;
 }
 
 static void dirty_map_exit(struct dm_clone_metadata *cmd)
 {
-       kvfree(cmd->dmap[0].dirty_words);
-       kvfree(cmd->dmap[1].dirty_words);
+       __dirty_map_exit(&cmd->dmap[0]);
+       __dirty_map_exit(&cmd->dmap[1]);
 }
 
 static int __load_bitset_in_core(struct dm_clone_metadata *cmd)
@@ -633,21 +667,23 @@ unsigned long dm_clone_find_next_unhydrated_region(struct dm_clone_metadata *cmd
        return find_next_zero_bit(cmd->region_map, cmd->nr_regions, start);
 }
 
-static int __update_metadata_word(struct dm_clone_metadata *cmd, unsigned long word)
+static int __update_metadata_word(struct dm_clone_metadata *cmd,
+                                 unsigned long *dirty_regions,
+                                 unsigned long word)
 {
        int r;
        unsigned long index = word * BITS_PER_LONG;
        unsigned long max_index = min(cmd->nr_regions, (word + 1) * BITS_PER_LONG);
 
        while (index < max_index) {
-               if (test_bit(index, cmd->region_map)) {
+               if (test_bit(index, dirty_regions)) {
                        r = dm_bitset_set_bit(&cmd->bitset_info, cmd->bitset_root,
                                              index, &cmd->bitset_root);
-
                        if (r) {
                                DMERR("dm_bitset_set_bit failed");
                                return r;
                        }
+                       __clear_bit(index, dirty_regions);
                }
                index++;
        }
@@ -721,7 +757,7 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap)
                if (word == cmd->nr_words)
                        break;
 
-               r = __update_metadata_word(cmd, word);
+               r = __update_metadata_word(cmd, dmap->dirty_regions, word);
 
                if (r)
                        return r;
@@ -743,15 +779,17 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap)
        return 0;
 }
 
-int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd)
 {
-       int r = -EPERM;
+       int r = 0;
        struct dirty_map *dmap, *next_dmap;
 
        down_write(&cmd->lock);
 
-       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) {
+               r = -EPERM;
                goto out;
+       }
 
        /* Get current dirty bitmap */
        dmap = cmd->current_dmap;
@@ -763,7 +801,7 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
         * The last commit failed, so we don't have a clean dirty-bitmap to
         * use.
         */
-       if (WARN_ON(next_dmap->changed)) {
+       if (WARN_ON(next_dmap->changed || cmd->committing_dmap)) {
                r = -EINVAL;
                goto out;
        }
@@ -773,11 +811,33 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
        cmd->current_dmap = next_dmap;
        spin_unlock_irq(&cmd->bitmap_lock);
 
-       /*
-        * No one is accessing the old dirty bitmap anymore, so we can flush
-        * it.
-        */
-       r = __flush_dmap(cmd, dmap);
+       /* Set old dirty bitmap as currently committing */
+       cmd->committing_dmap = dmap;
+out:
+       up_write(&cmd->lock);
+
+       return r;
+}
+
+int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+{
+       int r = -EPERM;
+
+       down_write(&cmd->lock);
+
+       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+               goto out;
+
+       if (WARN_ON(!cmd->committing_dmap)) {
+               r = -EINVAL;
+               goto out;
+       }
+
+       r = __flush_dmap(cmd, cmd->committing_dmap);
+       if (!r) {
+               /* Clear committing dmap */
+               cmd->committing_dmap = NULL;
+       }
 out:
        up_write(&cmd->lock);
 
@@ -802,6 +862,7 @@ int dm_clone_set_region_hydrated(struct dm_clone_metadata *cmd, unsigned long re
        dmap = cmd->current_dmap;
 
        __set_bit(word, dmap->dirty_words);
+       __set_bit(region_nr, dmap->dirty_regions);
        __set_bit(region_nr, cmd->region_map);
        dmap->changed = 1;
 
@@ -830,6 +891,7 @@ int dm_clone_cond_set_range(struct dm_clone_metadata *cmd, unsigned long start,
                if (!test_bit(region_nr, cmd->region_map)) {
                        word = region_nr / BITS_PER_LONG;
                        __set_bit(word, dmap->dirty_words);
+                       __set_bit(region_nr, dmap->dirty_regions);
                        __set_bit(region_nr, cmd->region_map);
                        dmap->changed = 1;
                }
index 3fe50a7..14af1eb 100644 (file)
@@ -75,7 +75,23 @@ void dm_clone_metadata_close(struct dm_clone_metadata *cmd);
 
 /*
  * Commit dm-clone metadata to disk.
+ *
+ * We use a two phase commit:
+ *
+ * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for
+ *    committing. After this is called, all subsequent metadata updates, done
+ *    through either dm_clone_set_region_hydrated() or
+ *    dm_clone_cond_set_range(), will be part of the **next** transaction.
+ *
+ * 2. dm_clone_metadata_commit(): Actually commit the current transaction to
+ *    disk and start a new transaction.
+ *
+ * This allows dm-clone to flush the destination device after step (1) to
+ * ensure that all freshly hydrated regions, for which we are updating the
+ * metadata, are properly written to non-volatile storage and won't be lost in
+ * case of a crash.
  */
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd);
 int dm_clone_metadata_commit(struct dm_clone_metadata *cmd);
 
 /*
@@ -112,6 +128,7 @@ int dm_clone_metadata_abort(struct dm_clone_metadata *cmd);
  * Switches metadata to a read only mode. Once read-only mode has been entered
  * the following functions will return -EPERM:
  *
+ *   dm_clone_metadata_pre_commit()
  *   dm_clone_metadata_commit()
  *   dm_clone_set_region_hydrated()
  *   dm_clone_cond_set_range()
index b3d8907..d1e1b5b 100644 (file)
@@ -86,6 +86,12 @@ struct clone {
 
        struct dm_clone_metadata *cmd;
 
+       /*
+        * bio used to flush the destination device, before committing the
+        * metadata.
+        */
+       struct bio flush_bio;
+
        /* Region hydration hash table */
        struct hash_table_bucket *ht;
 
@@ -1108,10 +1114,13 @@ static bool need_commit_due_to_time(struct clone *clone)
 /*
  * A non-zero return indicates read-only or fail mode.
  */
-static int commit_metadata(struct clone *clone)
+static int commit_metadata(struct clone *clone, bool *dest_dev_flushed)
 {
        int r = 0;
 
+       if (dest_dev_flushed)
+               *dest_dev_flushed = false;
+
        mutex_lock(&clone->commit_lock);
 
        if (!dm_clone_changed_this_transaction(clone->cmd))
@@ -1122,8 +1131,26 @@ static int commit_metadata(struct clone *clone)
                goto out;
        }
 
-       r = dm_clone_metadata_commit(clone->cmd);
+       r = dm_clone_metadata_pre_commit(clone->cmd);
+       if (unlikely(r)) {
+               __metadata_operation_failed(clone, "dm_clone_metadata_pre_commit", r);
+               goto out;
+       }
 
+       bio_reset(&clone->flush_bio);
+       bio_set_dev(&clone->flush_bio, clone->dest_dev->bdev);
+       clone->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+       r = submit_bio_wait(&clone->flush_bio);
+       if (unlikely(r)) {
+               __metadata_operation_failed(clone, "flush destination device", r);
+               goto out;
+       }
+
+       if (dest_dev_flushed)
+               *dest_dev_flushed = true;
+
+       r = dm_clone_metadata_commit(clone->cmd);
        if (unlikely(r)) {
                __metadata_operation_failed(clone, "dm_clone_metadata_commit", r);
                goto out;
@@ -1194,6 +1221,7 @@ static void process_deferred_bios(struct clone *clone)
 static void process_deferred_flush_bios(struct clone *clone)
 {
        struct bio *bio;
+       bool dest_dev_flushed;
        struct bio_list bios = BIO_EMPTY_LIST;
        struct bio_list bio_completions = BIO_EMPTY_LIST;
 
@@ -1213,7 +1241,7 @@ static void process_deferred_flush_bios(struct clone *clone)
            !(dm_clone_changed_this_transaction(clone->cmd) && need_commit_due_to_time(clone)))
                return;
 
-       if (commit_metadata(clone)) {
+       if (commit_metadata(clone, &dest_dev_flushed)) {
                bio_list_merge(&bios, &bio_completions);
 
                while ((bio = bio_list_pop(&bios)))
@@ -1227,8 +1255,17 @@ static void process_deferred_flush_bios(struct clone *clone)
        while ((bio = bio_list_pop(&bio_completions)))
                bio_endio(bio);
 
-       while ((bio = bio_list_pop(&bios)))
-               generic_make_request(bio);
+       while ((bio = bio_list_pop(&bios))) {
+               if ((bio->bi_opf & REQ_PREFLUSH) && dest_dev_flushed) {
+                       /* We just flushed the destination device as part of
+                        * the metadata commit, so there is no reason to send
+                        * another flush.
+                        */
+                       bio_endio(bio);
+               } else {
+                       generic_make_request(bio);
+               }
+       }
 }
 
 static void do_worker(struct work_struct *work)
@@ -1400,7 +1437,7 @@ static void clone_status(struct dm_target *ti, status_type_t type,
 
                /* Commit to ensure statistics aren't out-of-date */
                if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-                       (void) commit_metadata(clone);
+                       (void) commit_metadata(clone, NULL);
 
                r = dm_clone_get_free_metadata_block_count(clone->cmd, &nr_free_metadata_blocks);
 
@@ -1834,6 +1871,7 @@ static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        bio_list_init(&clone->deferred_flush_completions);
        clone->hydration_offset = 0;
        atomic_set(&clone->hydrations_in_flight, 0);
+       bio_init(&clone->flush_bio, NULL, 0);
 
        clone->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0);
        if (!clone->wq) {
@@ -1907,6 +1945,7 @@ static void clone_dtr(struct dm_target *ti)
        struct clone *clone = ti->private;
 
        mutex_destroy(&clone->commit_lock);
+       bio_uninit(&clone->flush_bio);
 
        for (i = 0; i < clone->nr_ctr_args; i++)
                kfree(clone->ctr_args[i]);
@@ -1961,7 +2000,7 @@ static void clone_postsuspend(struct dm_target *ti)
        wait_event(clone->hydration_stopped, !atomic_read(&clone->hydrations_in_flight));
        flush_workqueue(clone->wq);
 
-       (void) commit_metadata(clone);
+       (void) commit_metadata(clone, NULL);
 }
 
 static void clone_resume(struct dm_target *ti)
index dbcc1e4..e0c3279 100644 (file)
@@ -599,45 +599,10 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
        return pgpath;
 }
 
-static struct pgpath *__map_bio_fast(struct multipath *m, struct bio *bio)
-{
-       struct pgpath *pgpath;
-       unsigned long flags;
-
-       /* Do we need to select a new pgpath? */
-       /*
-        * FIXME: currently only switching path if no path (due to failure, etc)
-        * - which negates the point of using a path selector
-        */
-       pgpath = READ_ONCE(m->current_pgpath);
-       if (!pgpath)
-               pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
-
-       if (!pgpath) {
-               if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-                       /* Queue for the daemon to resubmit */
-                       spin_lock_irqsave(&m->lock, flags);
-                       bio_list_add(&m->queued_bios, bio);
-                       spin_unlock_irqrestore(&m->lock, flags);
-                       queue_work(kmultipathd, &m->process_queued_bios);
-
-                       return ERR_PTR(-EAGAIN);
-               }
-               return NULL;
-       }
-
-       return pgpath;
-}
-
 static int __multipath_map_bio(struct multipath *m, struct bio *bio,
                               struct dm_mpath_io *mpio)
 {
-       struct pgpath *pgpath;
-
-       if (!m->hw_handler_name)
-               pgpath = __map_bio_fast(m, bio);
-       else
-               pgpath = __map_bio(m, bio);
+       struct pgpath *pgpath = __map_bio(m, bio);
 
        if (IS_ERR(pgpath))
                return DM_MAPIO_SUBMITTED;
index 4c68a7b..b88d6d7 100644 (file)
@@ -189,6 +189,15 @@ struct dm_pool_metadata {
        sector_t data_block_size;
 
        /*
+        * Pre-commit callback.
+        *
+        * This allows the thin provisioning target to run a callback before
+        * the metadata are committed.
+        */
+       dm_pool_pre_commit_fn pre_commit_fn;
+       void *pre_commit_context;
+
+       /*
         * We reserve a section of the metadata for commit overhead.
         * All reported space does *not* include this.
         */
@@ -826,6 +835,14 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
        if (unlikely(!pmd->in_service))
                return 0;
 
+       if (pmd->pre_commit_fn) {
+               r = pmd->pre_commit_fn(pmd->pre_commit_context);
+               if (r < 0) {
+                       DMERR("pre-commit callback failed");
+                       return r;
+               }
+       }
+
        r = __write_changed_details(pmd);
        if (r < 0)
                return r;
@@ -892,6 +909,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
        pmd->in_service = false;
        pmd->bdev = bdev;
        pmd->data_block_size = data_block_size;
+       pmd->pre_commit_fn = NULL;
+       pmd->pre_commit_context = NULL;
 
        r = __create_persistent_data_objects(pmd, format_device);
        if (r) {
@@ -2044,6 +2063,16 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
        return r;
 }
 
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+                                         dm_pool_pre_commit_fn fn,
+                                         void *context)
+{
+       pmd_write_lock_in_core(pmd);
+       pmd->pre_commit_fn = fn;
+       pmd->pre_commit_context = context;
+       pmd_write_unlock(pmd);
+}
+
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
index f6be0d7..7ef56bd 100644 (file)
@@ -230,6 +230,13 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
  */
 void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd);
 
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+                                         dm_pool_pre_commit_fn fn,
+                                         void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
index 5a2c494..57626c2 100644 (file)
@@ -328,6 +328,7 @@ struct pool_c {
        dm_block_t low_water_blocks;
        struct pool_features requested_pf; /* Features requested during table load */
        struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
+       struct bio flush_bio;
 };
 
 /*
@@ -2383,8 +2384,16 @@ static void process_deferred_bios(struct pool *pool)
        while ((bio = bio_list_pop(&bio_completions)))
                bio_endio(bio);
 
-       while ((bio = bio_list_pop(&bios)))
-               generic_make_request(bio);
+       while ((bio = bio_list_pop(&bios))) {
+               /*
+                * The data device was flushed as part of metadata commit,
+                * so complete redundant flushes immediately.
+                */
+               if (bio->bi_opf & REQ_PREFLUSH)
+                       bio_endio(bio);
+               else
+                       generic_make_request(bio);
+       }
 }
 
 static void do_worker(struct work_struct *ws)
@@ -3115,6 +3124,7 @@ static void pool_dtr(struct dm_target *ti)
        __pool_dec(pt->pool);
        dm_put_device(ti, pt->metadata_dev);
        dm_put_device(ti, pt->data_dev);
+       bio_uninit(&pt->flush_bio);
        kfree(pt);
 
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -3180,6 +3190,29 @@ static void metadata_low_callback(void *context)
        dm_table_event(pool->ti->table);
 }
 
+/*
+ * We need to flush the data device **before** committing the metadata.
+ *
+ * This ensures that the data blocks of any newly inserted mappings are
+ * properly written to non-volatile storage and won't be lost in case of a
+ * crash.
+ *
+ * Failure to do so can result in data corruption in the case of internal or
+ * external snapshots and in the case of newly provisioned blocks, when block
+ * zeroing is enabled.
+ */
+static int metadata_pre_commit_callback(void *context)
+{
+       struct pool_c *pt = context;
+       struct bio *flush_bio = &pt->flush_bio;
+
+       bio_reset(flush_bio);
+       bio_set_dev(flush_bio, pt->data_dev->bdev);
+       flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+       return submit_bio_wait(flush_bio);
+}
+
 static sector_t get_dev_size(struct block_device *bdev)
 {
        return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
@@ -3348,6 +3381,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
        pt->adjusted_pf = pt->requested_pf = pf;
+       bio_init(&pt->flush_bio, NULL, 0);
        ti->num_flush_bios = 1;
 
        /*
@@ -3374,6 +3408,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (r)
                goto out_flags_changed;
 
+       dm_pool_register_pre_commit_callback(pt->pool->pmd,
+                                            metadata_pre_commit_callback,
+                                            pt);
+
        pt->callbacks.congested_fn = pool_is_congested;
        dm_table_add_target_callbacks(ti->table, &pt->callbacks);
 
index 805b33e..4e7c9f3 100644 (file)
@@ -1159,6 +1159,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
        /* not spare disk, or LEVEL_MULTIPATH */
        if (sb->level == LEVEL_MULTIPATH ||
                (rdev->desc_nr >= 0 &&
+                rdev->desc_nr < MD_SB_DISKS &&
                 sb->disks[rdev->desc_nr].state &
                 ((1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE))))
                spare_disk = false;
index 21ea537..eff04fa 100644 (file)
@@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
        struct btree_node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-       unsigned threshold = 2 * merge_threshold(left) + 1;
+       /*
+        * Ensure the number of entries in each child will be greater
+        * than or equal to (max_entries / 3 + 1), so no matter which
+        * child is used for removal, the number will still be not
+        * less than (max_entries / 3).
+        */
+       unsigned int threshold = 2 * (merge_threshold(left) + 1);
 
        if (nr_left + nr_right < threshold) {
                /*
index a409ab6..201fd8a 100644 (file)
@@ -2782,7 +2782,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
                                write_targets++;
                        }
                }
-               if (bio->bi_end_io) {
+               if (rdev && bio->bi_end_io) {
                        atomic_inc(&rdev->nr_pending);
                        bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
                        bio_set_dev(bio, rdev->bdev);
index cab5b13..d50238d 100644 (file)
@@ -1360,7 +1360,7 @@ int ppl_init_log(struct r5conf *conf)
                return -EINVAL;
        }
 
-       max_disks = FIELD_SIZEOF(struct ppl_log, disk_flush_bitmap) *
+       max_disks = sizeof_field(struct ppl_log, disk_flush_bitmap) *
                BITS_PER_BYTE;
        if (conf->raid_disks > max_disks) {
                pr_warn("md/raid:%s PPL doesn't support over %d disks in the array\n",
index f0fc538..d4d3b67 100644 (file)
@@ -5726,7 +5726,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
                                do_flush = false;
                        }
 
-                       if (!sh->batch_head)
+                       if (!sh->batch_head || sh == sh->batch_head)
                                set_bit(STRIPE_HANDLE, &sh->state);
                        clear_bit(STRIPE_DELAYED, &sh->state);
                        if ((!sh->batch_head || sh == sh->batch_head) &&
index 97d6606..4dbdf31 100644 (file)
@@ -753,7 +753,7 @@ static const struct preview_update update_attrs[] = {
                preview_config_luma_enhancement,
                preview_enable_luma_enhancement,
                offsetof(struct prev_params, luma),
-               FIELD_SIZEOF(struct prev_params, luma),
+               sizeof_field(struct prev_params, luma),
                offsetof(struct omap3isp_prev_update_config, luma),
        }, /* OMAP3ISP_PREV_INVALAW */ {
                NULL,
@@ -762,55 +762,55 @@ static const struct preview_update update_attrs[] = {
                preview_config_hmed,
                preview_enable_hmed,
                offsetof(struct prev_params, hmed),
-               FIELD_SIZEOF(struct prev_params, hmed),
+               sizeof_field(struct prev_params, hmed),
                offsetof(struct omap3isp_prev_update_config, hmed),
        }, /* OMAP3ISP_PREV_CFA */ {
                preview_config_cfa,
                NULL,
                offsetof(struct prev_params, cfa),
-               FIELD_SIZEOF(struct prev_params, cfa),
+               sizeof_field(struct prev_params, cfa),
                offsetof(struct omap3isp_prev_update_config, cfa),
        }, /* OMAP3ISP_PREV_CHROMA_SUPP */ {
                preview_config_chroma_suppression,
                preview_enable_chroma_suppression,
                offsetof(struct prev_params, csup),
-               FIELD_SIZEOF(struct prev_params, csup),
+               sizeof_field(struct prev_params, csup),
                offsetof(struct omap3isp_prev_update_config, csup),
        }, /* OMAP3ISP_PREV_WB */ {
                preview_config_whitebalance,
                NULL,
                offsetof(struct prev_params, wbal),
-               FIELD_SIZEOF(struct prev_params, wbal),
+               sizeof_field(struct prev_params, wbal),
                offsetof(struct omap3isp_prev_update_config, wbal),
        }, /* OMAP3ISP_PREV_BLKADJ */ {
                preview_config_blkadj,
                NULL,
                offsetof(struct prev_params, blkadj),
-               FIELD_SIZEOF(struct prev_params, blkadj),
+               sizeof_field(struct prev_params, blkadj),
                offsetof(struct omap3isp_prev_update_config, blkadj),
        }, /* OMAP3ISP_PREV_RGB2RGB */ {
                preview_config_rgb_blending,
                NULL,
                offsetof(struct prev_params, rgb2rgb),
-               FIELD_SIZEOF(struct prev_params, rgb2rgb),
+               sizeof_field(struct prev_params, rgb2rgb),
                offsetof(struct omap3isp_prev_update_config, rgb2rgb),
        }, /* OMAP3ISP_PREV_COLOR_CONV */ {
                preview_config_csc,
                NULL,
                offsetof(struct prev_params, csc),
-               FIELD_SIZEOF(struct prev_params, csc),
+               sizeof_field(struct prev_params, csc),
                offsetof(struct omap3isp_prev_update_config, csc),
        }, /* OMAP3ISP_PREV_YC_LIMIT */ {
                preview_config_yc_range,
                NULL,
                offsetof(struct prev_params, yclimit),
-               FIELD_SIZEOF(struct prev_params, yclimit),
+               sizeof_field(struct prev_params, yclimit),
                offsetof(struct omap3isp_prev_update_config, yclimit),
        }, /* OMAP3ISP_PREV_DEFECT_COR */ {
                preview_config_dcor,
                preview_enable_dcor,
                offsetof(struct prev_params, dcor),
-               FIELD_SIZEOF(struct prev_params, dcor),
+               sizeof_field(struct prev_params, dcor),
                offsetof(struct omap3isp_prev_update_config, dcor),
        }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ {
                NULL,
@@ -828,13 +828,13 @@ static const struct preview_update update_attrs[] = {
                preview_config_noisefilter,
                preview_enable_noisefilter,
                offsetof(struct prev_params, nf),
-               FIELD_SIZEOF(struct prev_params, nf),
+               sizeof_field(struct prev_params, nf),
                offsetof(struct omap3isp_prev_update_config, nf),
        }, /* OMAP3ISP_PREV_GAMMA */ {
                preview_config_gammacorrn,
                preview_enable_gammacorrn,
                offsetof(struct prev_params, gamma),
-               FIELD_SIZEOF(struct prev_params, gamma),
+               sizeof_field(struct prev_params, gamma),
                offsetof(struct omap3isp_prev_update_config, gamma),
        }, /* OMAP3ISP_PREV_CONTRAST */ {
                preview_config_contrast,
index 4e70058..003b742 100644 (file)
@@ -2652,7 +2652,7 @@ struct v4l2_ioctl_info {
 /* Zero struct from after the field to the end */
 #define INFO_FL_CLEAR(v4l2_struct, field)                      \
        ((offsetof(struct v4l2_struct, field) +                 \
-         FIELD_SIZEOF(struct v4l2_struct, field)) << 16)
+         sizeof_field(struct v4l2_struct, field)) << 16)
 #define INFO_FL_CLEAR_MASK     (_IOC_SIZEMASK << 16)
 
 #define DEFINE_V4L_STUB_FUNC(_vidioc)                          \
index 8850f47..0bf0867 100644 (file)
@@ -824,8 +824,9 @@ int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
        memset(args, 0, sizeof(*args));
 
        if (rc < 0) {
-               dev_err(hdev->dev, "Error %ld on waiting for CS handle %llu\n",
-                       rc, seq);
+               dev_err_ratelimited(hdev->dev,
+                               "Error %ld on waiting for CS handle %llu\n",
+                               rc, seq);
                if (rc == -ERESTARTSYS) {
                        args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED;
                        rc = -EINTR;
index 17db7b3..2df6fb8 100644 (file)
@@ -176,7 +176,7 @@ struct dma_fence *hl_ctx_get_fence(struct hl_ctx *ctx, u64 seq)
        spin_lock(&ctx->cs_lock);
 
        if (seq >= ctx->cs_sequence) {
-               dev_notice(hdev->dev,
+               dev_notice_ratelimited(hdev->dev,
                        "Can't wait on seq %llu because current CS is at seq %llu\n",
                        seq, ctx->cs_sequence);
                spin_unlock(&ctx->cs_lock);
index c8d16aa..7344e8a 100644 (file)
@@ -2192,7 +2192,7 @@ static int goya_push_linux_to_device(struct hl_device *hdev)
 
 static int goya_pldm_init_cpu(struct hl_device *hdev)
 {
-       u32 val, unit_rst_val;
+       u32 unit_rst_val;
        int rc;
 
        /* Must initialize SRAM scrambler before pushing u-boot to SRAM */
@@ -2200,14 +2200,14 @@ static int goya_pldm_init_cpu(struct hl_device *hdev)
 
        /* Put ARM cores into reset */
        WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, CPU_RESET_ASSERT);
-       val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+       RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
        /* Reset the CA53 MACRO */
        unit_rst_val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
        WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, CA53_RESET);
-       val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+       RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
        WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, unit_rst_val);
-       val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+       RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
 
        rc = goya_push_uboot_to_device(hdev);
        if (rc)
@@ -2228,7 +2228,7 @@ static int goya_pldm_init_cpu(struct hl_device *hdev)
        /* Release ARM core 0 from reset */
        WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL,
                                        CPU_RESET_CORE0_DEASSERT);
-       val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+       RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
        return 0;
 }
@@ -2502,13 +2502,12 @@ err:
 static int goya_hw_init(struct hl_device *hdev)
 {
        struct asic_fixed_properties *prop = &hdev->asic_prop;
-       u32 val;
        int rc;
 
        dev_info(hdev->dev, "Starting initialization of H/W\n");
 
        /* Perform read from the device to make sure device is up */
-       val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+       RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
        /*
         * Let's mark in the H/W that we have reached this point. We check
@@ -2560,7 +2559,7 @@ static int goya_hw_init(struct hl_device *hdev)
                goto disable_queues;
 
        /* Perform read from the device to flush all MSI-X configuration */
-       val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+       RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
        return 0;
 
index 994563a..de8a66b 100644 (file)
@@ -10,18 +10,17 @@ int ocxl_context_alloc(struct ocxl_context **context, struct ocxl_afu *afu,
        int pasid;
        struct ocxl_context *ctx;
 
-       *context = kzalloc(sizeof(struct ocxl_context), GFP_KERNEL);
-       if (!*context)
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
                return -ENOMEM;
 
-       ctx = *context;
-
        ctx->afu = afu;
        mutex_lock(&afu->contexts_lock);
        pasid = idr_alloc(&afu->contexts_idr, ctx, afu->pasid_base,
                        afu->pasid_base + afu->pasid_max, GFP_KERNEL);
        if (pasid < 0) {
                mutex_unlock(&afu->contexts_lock);
+               kfree(ctx);
                return pasid;
        }
        afu->pasid_count++;
@@ -43,6 +42,7 @@ int ocxl_context_alloc(struct ocxl_context **context, struct ocxl_afu *afu,
         * duration of the life of the context
         */
        ocxl_afu_get(afu);
+       *context = ctx;
        return 0;
 }
 EXPORT_SYMBOL_GPL(ocxl_context_alloc);
index 2870c25..4d1b44d 100644 (file)
@@ -18,18 +18,15 @@ static struct class *ocxl_class;
 static struct mutex minors_idr_lock;
 static struct idr minors_idr;
 
-static struct ocxl_file_info *find_file_info(dev_t devno)
+static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
 {
        struct ocxl_file_info *info;
 
-       /*
-        * We don't declare an RCU critical section here, as our AFU
-        * is protected by a reference counter on the device. By the time the
-        * info reference is removed from the idr, the ref count of
-        * the device is already at 0, so no user API will access that AFU and
-        * this function can't return it.
-        */
+       mutex_lock(&minors_idr_lock);
        info = idr_find(&minors_idr, MINOR(devno));
+       if (info)
+               get_device(&info->dev);
+       mutex_unlock(&minors_idr_lock);
        return info;
 }
 
@@ -58,14 +55,16 @@ static int afu_open(struct inode *inode, struct file *file)
 
        pr_debug("%s for device %x\n", __func__, inode->i_rdev);
 
-       info = find_file_info(inode->i_rdev);
+       info = find_and_get_file_info(inode->i_rdev);
        if (!info)
                return -ENODEV;
 
        rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
-       if (rc)
+       if (rc) {
+               put_device(&info->dev);
                return rc;
-
+       }
+       put_device(&info->dev);
        file->private_data = ctx;
        return 0;
 }
@@ -487,7 +486,6 @@ static void info_release(struct device *dev)
 {
        struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
 
-       free_minor(info);
        ocxl_afu_put(info->afu);
        kfree(info);
 }
@@ -577,6 +575,7 @@ void ocxl_file_unregister_afu(struct ocxl_afu *afu)
 
        ocxl_file_make_invisible(info);
        ocxl_sysfs_unregister_afu(info);
+       free_minor(info);
        device_unregister(&info->dev);
 }
 
index 189e426..010fe29 100644 (file)
 #define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29)  /* RW */
 #define MSDC_PATCH_BIT_DECRCTMO   (0x1 << 30)  /* RW */
 
+#define MSDC_PATCH_BIT1_CMDTA     (0x7 << 3)    /* RW */
 #define MSDC_PATCH_BIT1_STOP_DLY  (0xf << 8)    /* RW */
 
 #define MSDC_PATCH_BIT2_CFGRESP   (0x1 << 15)   /* RW */
@@ -1881,6 +1882,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)
 
        /* select EMMC50 PAD CMD tune */
        sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0));
+       sdr_set_field(host->base + MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMDTA, 2);
 
        if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
            mmc->ios.timing == MMC_TIMING_UHS_SDR104)
index b75c82d..3d0bb5e 100644 (file)
@@ -99,7 +99,7 @@
 
 #define CORE_PWRSAVE_DLL       BIT(3)
 
-#define DDR_CONFIG_POR_VAL     0x80040853
+#define DDR_CONFIG_POR_VAL     0x80040873
 
 
 #define INVALID_TUNING_PHASE   -1
@@ -148,8 +148,9 @@ struct sdhci_msm_offset {
        u32 core_ddr_200_cfg;
        u32 core_vendor_spec3;
        u32 core_dll_config_2;
+       u32 core_dll_config_3;
+       u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */
        u32 core_ddr_config;
-       u32 core_ddr_config_2;
 };
 
 static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
@@ -177,8 +178,8 @@ static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
        .core_ddr_200_cfg = 0x224,
        .core_vendor_spec3 = 0x250,
        .core_dll_config_2 = 0x254,
-       .core_ddr_config = 0x258,
-       .core_ddr_config_2 = 0x25c,
+       .core_dll_config_3 = 0x258,
+       .core_ddr_config = 0x25c,
 };
 
 static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
@@ -207,8 +208,8 @@ static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
        .core_ddr_200_cfg = 0x184,
        .core_vendor_spec3 = 0x1b0,
        .core_dll_config_2 = 0x1b4,
-       .core_ddr_config = 0x1b8,
-       .core_ddr_config_2 = 0x1bc,
+       .core_ddr_config_old = 0x1b8,
+       .core_ddr_config = 0x1bc,
 };
 
 struct sdhci_msm_variant_ops {
@@ -253,6 +254,7 @@ struct sdhci_msm_host {
        const struct sdhci_msm_offset *offset;
        bool use_cdr;
        u32 transfer_mode;
+       bool updated_ddr_cfg;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -924,8 +926,10 @@ out:
 static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 {
        struct mmc_host *mmc = host->mmc;
-       u32 dll_status, config;
+       u32 dll_status, config, ddr_cfg_offset;
        int ret;
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
        const struct sdhci_msm_offset *msm_offset =
                                        sdhci_priv_msm_offset(host);
 
@@ -938,8 +942,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
         * bootloaders. In the future, if this changes, then the desired
         * values will need to be programmed appropriately.
         */
-       writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr +
-                       msm_offset->core_ddr_config);
+       if (msm_host->updated_ddr_cfg)
+               ddr_cfg_offset = msm_offset->core_ddr_config;
+       else
+               ddr_cfg_offset = msm_offset->core_ddr_config_old;
+       writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + ddr_cfg_offset);
 
        if (mmc->ios.enhanced_strobe) {
                config = readl_relaxed(host->ioaddr +
@@ -1899,6 +1906,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
                                msm_offset->core_vendor_spec_capabilities0);
        }
 
+       if (core_major == 1 && core_minor >= 0x49)
+               msm_host->updated_ddr_cfg = true;
+
        /*
         * Power on reset state may trigger power irq if previous status of
         * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
index 5cca3fa..500f70a 100644 (file)
@@ -80,6 +80,7 @@ struct sdhci_esdhc {
        bool quirk_tuning_erratum_type1;
        bool quirk_tuning_erratum_type2;
        bool quirk_ignore_data_inhibit;
+       bool quirk_delay_before_data_reset;
        bool in_sw_tuning;
        unsigned int peripheral_clock;
        const struct esdhc_clk_fixup *clk_fixup;
@@ -759,14 +760,16 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
        struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
        u32 val;
 
+       if (esdhc->quirk_delay_before_data_reset &&
+           (mask & SDHCI_RESET_DATA) &&
+           (host->flags & SDHCI_REQ_USE_DMA))
+               mdelay(5);
+
        sdhci_reset(host, mask);
 
        sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
        sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
-       if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"))
-               mdelay(5);
-
        if (mask & SDHCI_RESET_ALL) {
                val = sdhci_readl(host, ESDHC_TBCTL);
                val &= ~ESDHC_TB_EN;
@@ -1221,6 +1224,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
        if (match)
                esdhc->clk_fixup = match->data;
        np = pdev->dev.of_node;
+
+       if (of_device_is_compatible(np, "fsl,p2020-esdhc"))
+               esdhc->quirk_delay_before_data_reset = true;
+
        clk = of_clk_get(np, 0);
        if (!IS_ERR(clk)) {
                /*
@@ -1303,8 +1310,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
                host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 
        if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) {
-               host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
-               host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+               host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
+               host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
        }
 
        if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
index acefb76..5091e2c 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/sdhci-pci-data.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86
 #include <asm/iosf_mbi.h>
@@ -783,11 +784,18 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
        return 0;
 }
 
+static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
+{
+       return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
+              dmi_match(DMI_BIOS_VENDOR, "LENOVO");
+}
+
 static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        int ret = byt_emmc_probe_slot(slot);
 
-       slot->host->mmc->caps2 |= MMC_CAP2_CQE;
+       if (!glk_broken_cqhci(slot))
+               slot->host->mmc->caps2 |= MMC_CAP2_CQE;
 
        if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
                slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
index 3140fe2..1b1c26d 100644 (file)
@@ -1882,9 +1882,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
        else if (timing == MMC_TIMING_UHS_SDR12)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-       else if (timing == MMC_TIMING_SD_HS ||
-                timing == MMC_TIMING_MMC_HS ||
-                timing == MMC_TIMING_UHS_SDR25)
+       else if (timing == MMC_TIMING_UHS_SDR25)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
        else if (timing == MMC_TIMING_UHS_SDR50)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
@@ -2419,8 +2417,8 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
                sdhci_send_tuning(host, opcode);
 
                if (!host->tuning_done) {
-                       pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
-                               mmc_hostname(host->mmc));
+                       pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
+                                mmc_hostname(host->mmc));
                        sdhci_abort_tuning(host, opcode);
                        return -ETIMEDOUT;
                }
@@ -3769,6 +3767,9 @@ int sdhci_setup_host(struct sdhci_host *host)
                       mmc_hostname(mmc), host->version);
        }
 
+       if (host->quirks & SDHCI_QUIRK_BROKEN_CQE)
+               mmc->caps2 &= ~MMC_CAP2_CQE;
+
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
        else if (!(host->caps & SDHCI_CAN_DO_SDMA))
index 0ed3e0e..fe83ece 100644 (file)
@@ -409,6 +409,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_CARD_DETECTION              (1<<15)
 /* Controller reports inverted write-protect state */
 #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT             (1<<16)
+/* Controller has unusable command queue engine */
+#define SDHCI_QUIRK_BROKEN_CQE                         (1<<17)
 /* Controller does not like fast PIO transfers */
 #define SDHCI_QUIRK_PIO_NEEDS_DELAY                    (1<<18)
 /* Controller does not have a LED */
index a880f10..8083173 100644 (file)
@@ -129,13 +129,13 @@ struct xgbe_stats {
 
 #define XGMAC_MMC_STAT(_string, _var)                          \
        { _string,                                              \
-         FIELD_SIZEOF(struct xgbe_mmc_stats, _var),            \
+         sizeof_field(struct xgbe_mmc_stats, _var),            \
          offsetof(struct xgbe_prv_data, mmc_stats._var),       \
        }
 
 #define XGMAC_EXT_STAT(_string, _var)                          \
        { _string,                                              \
-         FIELD_SIZEOF(struct xgbe_ext_stats, _var),            \
+         sizeof_field(struct xgbe_ext_stats, _var),            \
          offsetof(struct xgbe_prv_data, ext_stats._var),       \
        }
 
index 0cc2338..dfc7750 100644 (file)
@@ -205,11 +205,11 @@ static int __cvmx_bootmem_check_version(struct octeon_device *oct,
        major_version = (u32)__cvmx_bootmem_desc_get(
                        oct, oct->bootmem_desc_addr,
                        offsetof(struct cvmx_bootmem_desc, major_version),
-                       FIELD_SIZEOF(struct cvmx_bootmem_desc, major_version));
+                       sizeof_field(struct cvmx_bootmem_desc, major_version));
        minor_version = (u32)__cvmx_bootmem_desc_get(
                        oct, oct->bootmem_desc_addr,
                        offsetof(struct cvmx_bootmem_desc, minor_version),
-                       FIELD_SIZEOF(struct cvmx_bootmem_desc, minor_version));
+                       sizeof_field(struct cvmx_bootmem_desc, minor_version));
 
        dev_dbg(&oct->pci_dev->dev, "%s: major_version=%d\n", __func__,
                major_version);
@@ -237,13 +237,13 @@ static const struct cvmx_bootmem_named_block_desc
                                oct, named_addr,
                                offsetof(struct cvmx_bootmem_named_block_desc,
                                         base_addr),
-                               FIELD_SIZEOF(
+                               sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        base_addr));
                desc->size = __cvmx_bootmem_desc_get(oct, named_addr,
                                offsetof(struct cvmx_bootmem_named_block_desc,
                                         size),
-                               FIELD_SIZEOF(
+                               sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        size));
 
@@ -268,20 +268,20 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 named_block_array_addr),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     named_block_array_addr));
                u32 num_blocks = (u32)__cvmx_bootmem_desc_get(
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 nb_num_blocks),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     nb_num_blocks));
 
                u32 name_length = (u32)__cvmx_bootmem_desc_get(
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 named_block_name_len),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     named_block_name_len));
 
                u64 named_addr = named_block_array_addr;
@@ -292,7 +292,7 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
                                         offsetof(
                                        struct cvmx_bootmem_named_block_desc,
                                        size),
-                                        FIELD_SIZEOF(
+                                        sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        size));
 
index 5bb5abf..022a54a 100644 (file)
@@ -23,7 +23,7 @@ struct be_ethtool_stat {
 };
 
 enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
-#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
+#define FIELDINFO(_struct, field) sizeof_field(_struct, field), \
                                        offsetof(_struct, field)
 #define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
                                        FIELDINFO(struct be_tx_stats, field)
index d862e9b..13dbd24 100644 (file)
@@ -10240,7 +10240,7 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
                return ret;
        }
 
-       data_len_per_desc = FIELD_SIZEOF(struct hclge_desc, data);
+       data_len_per_desc = sizeof_field(struct hclge_desc, data);
        *len = 0;
        for (i = 0; i < dfx_reg_type_num; i++) {
                bd_num = bd_num_list[i];
index fbc39a2..180224e 100644 (file)
@@ -614,7 +614,7 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
        }
 
        memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc,
-              FIELD_SIZEOF(struct hnae3_knic_private_info, prio_tc));
+              sizeof_field(struct hnae3_knic_private_info, prio_tc));
 }
 
 static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
index 60ec48f..966aea9 100644 (file)
@@ -450,7 +450,7 @@ static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
 
 #define HINIC_FUNC_STAT(_stat_item) {  \
        .name = #_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_vport_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_vport_stats, _stat_item), \
        .offset = offsetof(struct hinic_vport_stats, _stat_item) \
 }
 
@@ -477,7 +477,7 @@ static struct hinic_stats hinic_function_stats[] = {
 
 #define HINIC_PORT_STAT(_stat_item) { \
        .name = #_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_phy_port_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_phy_port_stats, _stat_item), \
        .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
 }
 
@@ -571,7 +571,7 @@ static struct hinic_stats hinic_port_stats[] = {
 
 #define HINIC_TXQ_STAT(_stat_item) { \
        .name = "txq%d_"#_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_txq_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_txq_stats, _stat_item), \
        .offset = offsetof(struct hinic_txq_stats, _stat_item) \
 }
 
@@ -586,7 +586,7 @@ static struct hinic_stats hinic_tx_queue_stats[] = {
 
 #define HINIC_RXQ_STAT(_stat_item) { \
        .name = "rxq%d_"#_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_rxq_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_rxq_stats, _stat_item), \
        .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
 }
 
index c681d2d..68edf55 100644 (file)
@@ -18,7 +18,7 @@ struct fm10k_stats {
 
 #define FM10K_STAT_FIELDS(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index d24d873..317f3f1 100644 (file)
@@ -43,7 +43,7 @@ struct i40e_stats {
  */
 #define I40E_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index be24d42..a3da422 100644 (file)
@@ -659,7 +659,7 @@ i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw)
 
 #define I40E_HMC_STORE(_struct, _ele)          \
        offsetof(struct _struct, _ele),         \
-       FIELD_SIZEOF(struct _struct, _ele)
+       sizeof_field(struct _struct, _ele)
 
 struct i40e_context_ele {
        u16 offset;
index dad3eec..84c3d8d 100644 (file)
@@ -42,7 +42,7 @@ struct iavf_stats {
  */
 #define IAVF_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index aec3c6c..9ebd93e 100644 (file)
@@ -15,7 +15,7 @@ struct ice_stats {
 
 #define ICE_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
@@ -36,10 +36,10 @@ static int ice_q_stats_len(struct net_device *netdev)
 #define ICE_VSI_STATS_LEN      ARRAY_SIZE(ice_gstrings_vsi_stats)
 
 #define ICE_PFC_STATS_LEN ( \
-               (FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_rx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xon_rx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_tx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xon_tx)) \
+               (sizeof_field(struct ice_pf, stats.priority_xoff_rx) + \
+                sizeof_field(struct ice_pf, stats.priority_xon_rx) + \
+                sizeof_field(struct ice_pf, stats.priority_xoff_tx) + \
+                sizeof_field(struct ice_pf, stats.priority_xon_tx)) \
                 / sizeof(u64))
 #define ICE_ALL_STATS_LEN(n)   (ICE_PF_STATS_LEN + ICE_PFC_STATS_LEN + \
                                 ICE_VSI_STATS_LEN + ice_q_stats_len(n))
index ad34f22..0997d35 100644 (file)
@@ -302,7 +302,7 @@ struct ice_ctx_ele {
 
 #define ICE_CTX_STORE(_struct, _ele, _width, _lsb) {   \
        .offset = offsetof(struct _struct, _ele),       \
-       .size_of = FIELD_SIZEOF(struct _struct, _ele),  \
+       .size_of = sizeof_field(struct _struct, _ele),  \
        .width = _width,                                \
        .lsb = _lsb,                                    \
 }
index 3182b05..4690d6c 100644 (file)
@@ -26,7 +26,7 @@ struct igb_stats {
 
 #define IGB_STAT(_name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct igb_adapter, _stat), \
        .stat_offset = offsetof(struct igb_adapter, _stat) \
 }
 static const struct igb_stats igb_gstrings_stats[] = {
@@ -76,7 +76,7 @@ static const struct igb_stats igb_gstrings_stats[] = {
 
 #define IGB_NETDEV_STAT(_net_stat) { \
        .stat_string = __stringify(_net_stat), \
-       .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+       .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \
        .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
 }
 static const struct igb_stats igb_gstrings_net_stats[] = {
index ac98f1d..455c1cd 100644 (file)
@@ -16,7 +16,7 @@ struct igc_stats {
 
 #define IGC_STAT(_name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(struct igc_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct igc_adapter, _stat), \
        .stat_offset = offsetof(struct igc_adapter, _stat) \
 }
 
@@ -67,7 +67,7 @@ static const struct igc_stats igc_gstrings_stats[] = {
 
 #define IGC_NETDEV_STAT(_net_stat) { \
        .stat_string = __stringify(_net_stat), \
-       .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+       .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \
        .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
 }
 
index c8c93ac..c65eb1a 100644 (file)
@@ -19,10 +19,10 @@ struct ixgb_stats {
 };
 
 #define IXGB_STAT(m)           IXGB_STATS, \
-                               FIELD_SIZEOF(struct ixgb_adapter, m), \
+                               sizeof_field(struct ixgb_adapter, m), \
                                offsetof(struct ixgb_adapter, m)
 #define IXGB_NETDEV_STAT(m)    NETDEV_STATS, \
-                               FIELD_SIZEOF(struct net_device, m), \
+                               sizeof_field(struct net_device, m), \
                                offsetof(struct net_device, m)
 
 static struct ixgb_stats ixgb_gstrings_stats[] = {
index 54459b6..f7f309c 100644 (file)
@@ -31,14 +31,14 @@ struct ixgbe_stats {
 #define IXGBEVF_STAT(_name, _stat) { \
        .stat_string = _name, \
        .type = IXGBEVF_STATS, \
-       .sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct ixgbevf_adapter, _stat), \
        .stat_offset = offsetof(struct ixgbevf_adapter, _stat) \
 }
 
 #define IXGBEVF_NETDEV_STAT(_net_stat) { \
        .stat_string = #_net_stat, \
        .type = NETDEV_STATS, \
-       .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
+       .sizeof_stat = sizeof_field(struct net_device_stats, _net_stat), \
        .stat_offset = offsetof(struct net_device_stats, _net_stat) \
 }
 
index d5b6441..65a0932 100644 (file)
@@ -1432,11 +1432,11 @@ struct mv643xx_eth_stats {
 };
 
 #define SSTAT(m)                                               \
-       { #m, FIELD_SIZEOF(struct net_device_stats, m),         \
+       { #m, sizeof_field(struct net_device_stats, m),         \
          offsetof(struct net_device, stats.m), -1 }
 
 #define MIBSTAT(m)                                             \
-       { #m, FIELD_SIZEOF(struct mib_counters, m),             \
+       { #m, sizeof_field(struct mib_counters, m),             \
          -1, offsetof(struct mv643xx_eth_private, mib_counters.m) }
 
 static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
index a1202e5..8bf1f08 100644 (file)
@@ -611,7 +611,7 @@ static u32 ptys_get_active_port(struct mlx4_ptys_reg *ptys_reg)
 }
 
 #define MLX4_LINK_MODES_SZ \
-       (FIELD_SIZEOF(struct mlx4_ptys_reg, eth_proto_cap) * 8)
+       (sizeof_field(struct mlx4_ptys_reg, eth_proto_cap) * 8)
 
 enum ethtool_report {
        SUPPORTED = 0,
index c76da30..e4ec0e0 100644 (file)
@@ -87,10 +87,10 @@ static const struct rhashtable_params rhash_sa = {
         * value is not constant during the lifetime
         * of the key object.
         */
-       .key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) -
-                  FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
+       .key_len = sizeof_field(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) -
+                  sizeof_field(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
        .key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) +
-                     FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
+                     sizeof_field(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
        .head_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hash),
        .automatic_shrinking = true,
        .min_size = 1,
index d605774..9a48c43 100644 (file)
@@ -209,7 +209,7 @@ enum fs_i_lock_class {
 };
 
 static const struct rhashtable_params rhash_fte = {
-       .key_len = FIELD_SIZEOF(struct fs_fte, val),
+       .key_len = sizeof_field(struct fs_fte, val),
        .key_offset = offsetof(struct fs_fte, val),
        .head_offset = offsetof(struct fs_fte, hash),
        .automatic_shrinking = true,
@@ -217,7 +217,7 @@ static const struct rhashtable_params rhash_fte = {
 };
 
 static const struct rhashtable_params rhash_fg = {
-       .key_len = FIELD_SIZEOF(struct mlx5_flow_group, mask),
+       .key_len = sizeof_field(struct mlx5_flow_group, mask),
        .key_offset = offsetof(struct mlx5_flow_group, mask),
        .head_offset = offsetof(struct mlx5_flow_group, hash),
        .automatic_shrinking = true,
index c80bb83..0a721f6 100644 (file)
@@ -2652,17 +2652,17 @@ static int mem_ldx_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
        switch (meta->insn.off) {
        case offsetof(struct __sk_buff, len):
-               if (size != FIELD_SIZEOF(struct __sk_buff, len))
+               if (size != sizeof_field(struct __sk_buff, len))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, plen_reg(nfp_prog));
                break;
        case offsetof(struct __sk_buff, data):
-               if (size != FIELD_SIZEOF(struct __sk_buff, data))
+               if (size != sizeof_field(struct __sk_buff, data))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
                break;
        case offsetof(struct __sk_buff, data_end):
-               if (size != FIELD_SIZEOF(struct __sk_buff, data_end))
+               if (size != sizeof_field(struct __sk_buff, data_end))
                        return -EOPNOTSUPP;
                emit_alu(nfp_prog, dst,
                         plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
@@ -2683,12 +2683,12 @@ static int mem_ldx_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
        switch (meta->insn.off) {
        case offsetof(struct xdp_md, data):
-               if (size != FIELD_SIZEOF(struct xdp_md, data))
+               if (size != sizeof_field(struct xdp_md, data))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
                break;
        case offsetof(struct xdp_md, data_end):
-               if (size != FIELD_SIZEOF(struct xdp_md, data_end))
+               if (size != sizeof_field(struct xdp_md, data_end))
                        return -EOPNOTSUPP;
                emit_alu(nfp_prog, dst,
                         plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
index 8f73277..11c83a9 100644 (file)
@@ -15,7 +15,7 @@
 
 const struct rhashtable_params nfp_bpf_maps_neutral_params = {
        .nelem_hint             = 4,
-       .key_len                = FIELD_SIZEOF(struct bpf_map, id),
+       .key_len                = sizeof_field(struct bpf_map, id),
        .key_offset             = offsetof(struct nfp_bpf_neutral_map, map_id),
        .head_offset            = offsetof(struct nfp_bpf_neutral_map, l),
        .automatic_shrinking    = true,
index 95a0d39..ac02369 100644 (file)
@@ -374,7 +374,7 @@ nfp_bpf_map_alloc(struct nfp_app_bpf *bpf, struct bpf_offloaded_map *offmap)
        }
 
        use_map_size = DIV_ROUND_UP(offmap->map.value_size, 4) *
-                      FIELD_SIZEOF(struct nfp_bpf_map, use_map[0]);
+                      sizeof_field(struct nfp_bpf_map, use_map[0]);
 
        nfp_map = kzalloc(sizeof(*nfp_map) + use_map_size, GFP_USER);
        if (!nfp_map)
index 31d9459..e0c985f 100644 (file)
@@ -24,7 +24,7 @@ struct nfp_app;
 #define NFP_FL_STAT_ID_MU_NUM          GENMASK(31, 22)
 #define NFP_FL_STAT_ID_STAT            GENMASK(21, 0)
 
-#define NFP_FL_STATS_ELEM_RS           FIELD_SIZEOF(struct nfp_fl_stats_id, \
+#define NFP_FL_STATS_ELEM_RS           sizeof_field(struct nfp_fl_stats_id, \
                                                     init_unalloc)
 #define NFP_FLOWER_MASK_ENTRY_RS       256
 #define NFP_FLOWER_MASK_ELEMENT_RS     1
index 1a3008e..b36aa5b 100644 (file)
@@ -20,7 +20,7 @@ struct pch_gbe_stats {
 #define PCH_GBE_STAT(m)                                                \
 {                                                              \
        .string = #m,                                           \
-       .size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m),       \
+       .size = sizeof_field(struct pch_gbe_hw_stats, m),       \
        .offset = offsetof(struct pch_gbe_hw_stats, m),         \
 }
 
index c303a92..e8a1b27 100644 (file)
@@ -464,7 +464,7 @@ struct qede_fastpath {
        struct qede_tx_queue    *txq;
        struct qede_tx_queue    *xdp_tx;
 
-#define VEC_NAME_SIZE  (FIELD_SIZEOF(struct net_device, name) + 8)
+#define VEC_NAME_SIZE  (sizeof_field(struct net_device, name) + 8)
        char    name[VEC_NAME_SIZE];
 };
 
index a4cd6f2..75d83c3 100644 (file)
@@ -20,7 +20,7 @@ struct qlcnic_stats {
        int stat_offset;
 };
 
-#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
+#define QLC_SIZEOF(m) sizeof_field(struct qlcnic_adapter, m)
 #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
 static const u32 qlcnic_fw_dump_level[] = {
        0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
index 355cc81..cbc6b84 100644 (file)
@@ -37,7 +37,7 @@ struct fw_info {
        u8      chksum;
 } __packed;
 
-#define FW_OPCODE_SIZE FIELD_SIZEOF(struct rtl_fw_phy_action, code[0])
+#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
 
 static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
 {
index 0775b94..466483c 100644 (file)
@@ -30,7 +30,7 @@ struct sxgbe_stats {
 #define SXGBE_STAT(m)                                          \
 {                                                              \
        #m,                                                     \
-       FIELD_SIZEOF(struct sxgbe_extra_stats, m),              \
+       sizeof_field(struct sxgbe_extra_stats, m),              \
        offsetof(struct sxgbe_priv_data, xstats.m)              \
 }
 
index 1a76883..b29603e 100644 (file)
@@ -34,7 +34,7 @@ struct stmmac_stats {
 };
 
 #define STMMAC_STAT(m) \
-       { #m, FIELD_SIZEOF(struct stmmac_extra_stats, m),       \
+       { #m, sizeof_field(struct stmmac_extra_stats, m),       \
        offsetof(struct stmmac_priv, xstats.m)}
 
 static const struct stmmac_stats stmmac_gstrings_stats[] = {
@@ -163,7 +163,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 
 /* HW MAC Management counters (if supported) */
 #define STMMAC_MMC_STAT(m)     \
-       { #m, FIELD_SIZEOF(struct stmmac_counters, m),  \
+       { #m, sizeof_field(struct stmmac_counters, m),  \
        offsetof(struct stmmac_priv, mmc.m)}
 
 static const struct stmmac_stats stmmac_mmc[] = {
index 31248a6..fa54efe 100644 (file)
@@ -73,13 +73,13 @@ enum {
 };
 
 #define CPSW_STAT(m)           CPSW_STATS,                             \
-                               FIELD_SIZEOF(struct cpsw_hw_stats, m), \
+                               sizeof_field(struct cpsw_hw_stats, m), \
                                offsetof(struct cpsw_hw_stats, m)
 #define CPDMA_RX_STAT(m)       CPDMA_RX_STATS,                            \
-                               FIELD_SIZEOF(struct cpdma_chan_stats, m), \
+                               sizeof_field(struct cpdma_chan_stats, m), \
                                offsetof(struct cpdma_chan_stats, m)
 #define CPDMA_TX_STAT(m)       CPDMA_TX_STATS,                            \
-                               FIELD_SIZEOF(struct cpdma_chan_stats, m), \
+                               sizeof_field(struct cpdma_chan_stats, m), \
                                offsetof(struct cpdma_chan_stats, m)
 
 static const struct cpsw_stats cpsw_gstrings_stats[] = {
index 86a3f42..d6a192c 100644 (file)
@@ -783,28 +783,28 @@ struct netcp_ethtool_stat {
 #define GBE_STATSA_INFO(field)                                         \
 {                                                                      \
        "GBE_A:"#field, GBE_STATSA_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSB_INFO(field)                                         \
 {                                                                      \
        "GBE_B:"#field, GBE_STATSB_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSC_INFO(field)                                         \
 {                                                                      \
        "GBE_C:"#field, GBE_STATSC_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSD_INFO(field)                                         \
 {                                                                      \
        "GBE_D:"#field, GBE_STATSD_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
@@ -957,7 +957,7 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = {
 #define GBENU_STATS_HOST(field)                                        \
 {                                                              \
        "GBE_HOST:"#field, GBENU_STATS0_MODULE,                 \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
@@ -967,56 +967,56 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = {
 #define GBENU_STATS_P1(field)                                  \
 {                                                              \
        "GBE_P1:"#field, GBENU_STATS1_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P2(field)                                  \
 {                                                              \
        "GBE_P2:"#field, GBENU_STATS2_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P3(field)                                  \
 {                                                              \
        "GBE_P3:"#field, GBENU_STATS3_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P4(field)                                  \
 {                                                              \
        "GBE_P4:"#field, GBENU_STATS4_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P5(field)                                  \
 {                                                              \
        "GBE_P5:"#field, GBENU_STATS5_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P6(field)                                  \
 {                                                              \
        "GBE_P6:"#field, GBENU_STATS6_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P7(field)                                  \
 {                                                              \
        "GBE_P7:"#field, GBENU_STATS7_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P8(field)                                  \
 {                                                              \
        "GBE_P8:"#field, GBENU_STATS8_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
@@ -1607,21 +1607,21 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = {
 #define XGBE_STATS0_INFO(field)                                \
 {                                                      \
        "GBE_0:"#field, XGBE_STATS0_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
 #define XGBE_STATS1_INFO(field)                                \
 {                                                      \
        "GBE_1:"#field, XGBE_STATS1_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
 #define XGBE_STATS2_INFO(field)                                \
 {                                                      \
        "GBE_2:"#field, XGBE_STATS2_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
index 09f3604..746736c 100644 (file)
@@ -21,7 +21,7 @@ struct fjes_stats {
 
 #define FJES_STAT(name, stat) { \
        .stat_string = name, \
-       .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \
+       .sizeof_stat = sizeof_field(struct fjes_adapter, stat), \
        .stat_offset = offsetof(struct fjes_adapter, stat) \
 }
 
index 5c6b7fc..75757e9 100644 (file)
@@ -1156,7 +1156,7 @@ static void geneve_setup(struct net_device *dev)
 
 static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
        [IFLA_GENEVE_ID]                = { .type = NLA_U32 },
-       [IFLA_GENEVE_REMOTE]            = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_GENEVE_REMOTE]            = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_GENEVE_REMOTE6]           = { .len = sizeof(struct in6_addr) },
        [IFLA_GENEVE_TTL]               = { .type = NLA_U8 },
        [IFLA_GENEVE_TOS]               = { .type = NLA_U8 },
index eff8fef..02e6647 100644 (file)
@@ -571,7 +571,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
        /* Use the skb control buffer for building up the packet */
        BUILD_BUG_ON(sizeof(struct hv_netvsc_packet) >
-                       FIELD_SIZEOF(struct sk_buff, cb));
+                       sizeof_field(struct sk_buff, cb));
        packet = (struct hv_netvsc_packet *)skb->cb;
 
        packet->q_idx = skb_get_queue_mapping(skb);
index 34c1eab..389d19d 100644 (file)
@@ -865,7 +865,7 @@ static struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev,
        u16 len;
        bool need_tail;
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data)
+       BUILD_BUG_ON(sizeof_field(struct usbnet, data)
                                < sizeof(struct cdc_state));
 
        dev_dbg(&dev->udev->dev, "%s", __func__);
index 30e511c..9ce6d30 100644 (file)
@@ -2184,7 +2184,7 @@ static int __init usbnet_init(void)
 {
        /* Compiler should optimize this out. */
        BUILD_BUG_ON(
-               FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data));
+               sizeof_field(struct sk_buff, cb) < sizeof(struct skb_data));
 
        eth_random_addr(node_id);
        return 0;
index 4c34375..3ec6b50 100644 (file)
@@ -3069,10 +3069,10 @@ static void vxlan_raw_setup(struct net_device *dev)
 
 static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
        [IFLA_VXLAN_ID]         = { .type = NLA_U32 },
-       [IFLA_VXLAN_GROUP]      = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_VXLAN_GROUP]      = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_VXLAN_GROUP6]     = { .len = sizeof(struct in6_addr) },
        [IFLA_VXLAN_LINK]       = { .type = NLA_U32 },
-       [IFLA_VXLAN_LOCAL]      = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
+       [IFLA_VXLAN_LOCAL]      = { .len = sizeof_field(struct iphdr, saddr) },
        [IFLA_VXLAN_LOCAL6]     = { .len = sizeof(struct in6_addr) },
        [IFLA_VXLAN_TOS]        = { .type = NLA_U8 },
        [IFLA_VXLAN_TTL]        = { .type = NLA_U8 },
index fe14814..c604613 100644 (file)
@@ -774,7 +774,7 @@ void lbs_debugfs_remove_one(struct lbs_private *priv)
 
 #ifdef PROC_DEBUG
 
-#define item_size(n)   (FIELD_SIZEOF(struct lbs_private, n))
+#define item_size(n)   (sizeof_field(struct lbs_private, n))
 #define item_addr(n)   (offsetof(struct lbs_private, n))
 
 
index c386992..7cafcec 100644 (file)
@@ -36,11 +36,11 @@ struct mwifiex_cb {
 };
 
 /* size/addr for mwifiex_debug_info */
-#define item_size(n)           (FIELD_SIZEOF(struct mwifiex_debug_info, n))
+#define item_size(n)           (sizeof_field(struct mwifiex_debug_info, n))
 #define item_addr(n)           (offsetof(struct mwifiex_debug_info, n))
 
 /* size/addr for struct mwifiex_adapter */
-#define adapter_item_size(n)   (FIELD_SIZEOF(struct mwifiex_adapter, n))
+#define adapter_item_size(n)   (sizeof_field(struct mwifiex_adapter, n))
 #define adapter_item_addr(n)   (offsetof(struct mwifiex_adapter, n))
 
 struct mwifiex_debug_data {
index dfe37a5..667f18f 100644 (file)
@@ -1735,6 +1735,8 @@ static int nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid,
                if (ret)
                        dev_warn(ctrl->device,
                                 "Identify Descriptors failed (%d)\n", ret);
+               if (ret > 0)
+                       ret = 0;
        }
        return ret;
 }
@@ -2852,6 +2854,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                 * admin connect
                 */
                if (ctrl->cntlid != le16_to_cpu(id->cntlid)) {
+                       dev_err(ctrl->device,
+                               "Mismatching cntlid: Connect %u vs Identify "
+                               "%u, rejecting\n",
+                               ctrl->cntlid, le16_to_cpu(id->cntlid));
                        ret = -EINVAL;
                        goto out_free;
                }
index 679a721..5a70ac3 100644 (file)
@@ -95,7 +95,7 @@ struct nvme_fc_fcp_op {
 
 struct nvme_fcp_op_w_sgl {
        struct nvme_fc_fcp_op   op;
-       struct scatterlist      sgl[SG_CHUNK_SIZE];
+       struct scatterlist      sgl[NVME_INLINE_SG_CNT];
        uint8_t                 priv[0];
 };
 
@@ -342,7 +342,8 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
            !template->ls_req || !template->fcp_io ||
            !template->ls_abort || !template->fcp_abort ||
            !template->max_hw_queues || !template->max_sgl_segments ||
-           !template->max_dif_sgl_segments || !template->dma_boundary) {
+           !template->max_dif_sgl_segments || !template->dma_boundary ||
+           !template->module) {
                ret = -EINVAL;
                goto out_reghost_failed;
        }
@@ -2015,6 +2016,7 @@ nvme_fc_ctrl_free(struct kref *ref)
 {
        struct nvme_fc_ctrl *ctrl =
                container_of(ref, struct nvme_fc_ctrl, ref);
+       struct nvme_fc_lport *lport = ctrl->lport;
        unsigned long flags;
 
        if (ctrl->ctrl.tagset) {
@@ -2041,6 +2043,7 @@ nvme_fc_ctrl_free(struct kref *ref)
        if (ctrl->ctrl.opts)
                nvmf_free_options(ctrl->ctrl.opts);
        kfree(ctrl);
+       module_put(lport->ops->module);
 }
 
 static void
@@ -2141,7 +2144,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        freq->sg_table.sgl = freq->first_sgl;
        ret = sg_alloc_table_chained(&freq->sg_table,
                        blk_rq_nr_phys_segments(rq), freq->sg_table.sgl,
-                       SG_CHUNK_SIZE);
+                       NVME_INLINE_SG_CNT);
        if (ret)
                return -ENOMEM;
 
@@ -2150,7 +2153,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
                                op->nents, rq_dma_dir(rq));
        if (unlikely(freq->sg_cnt <= 0)) {
-               sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE);
+               sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT);
                freq->sg_cnt = 0;
                return -EFAULT;
        }
@@ -2173,7 +2176,7 @@ nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        fc_dma_unmap_sg(ctrl->lport->dev, freq->sg_table.sgl, op->nents,
                        rq_dma_dir(rq));
 
-       sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT);
 
        freq->sg_cnt = 0;
 }
@@ -2910,10 +2913,22 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 static void
 __nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
 {
-       nvme_stop_keep_alive(&ctrl->ctrl);
+       /*
+        * if state is connecting - the error occurred as part of a
+        * reconnect attempt. The create_association error paths will
+        * clean up any outstanding io.
+        *
+        * if it's a different state - ensure all pending io is
+        * terminated. Given this can delay while waiting for the
+        * aborted io to return, we recheck adapter state below
+        * before changing state.
+        */
+       if (ctrl->ctrl.state != NVME_CTRL_CONNECTING) {
+               nvme_stop_keep_alive(&ctrl->ctrl);
 
-       /* will block will waiting for io to terminate */
-       nvme_fc_delete_association(ctrl);
+               /* will block will waiting for io to terminate */
+               nvme_fc_delete_association(ctrl);
+       }
 
        if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
            !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
@@ -3059,10 +3074,15 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
                goto out_fail;
        }
 
+       if (!try_module_get(lport->ops->module)) {
+               ret = -EUNATCH;
+               goto out_free_ctrl;
+       }
+
        idx = ida_simple_get(&nvme_fc_ctrl_cnt, 0, 0, GFP_KERNEL);
        if (idx < 0) {
                ret = -ENOSPC;
-               goto out_free_ctrl;
+               goto out_mod_put;
        }
 
        ctrl->ctrl.opts = opts;
@@ -3215,6 +3235,8 @@ out_free_queues:
 out_free_ida:
        put_device(ctrl->dev);
        ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum);
+out_mod_put:
+       module_put(lport->ops->module);
 out_free_ctrl:
        kfree(ctrl);
 out_fail:
index 3b9cbe0..1024fec 100644 (file)
@@ -28,6 +28,12 @@ extern unsigned int admin_timeout;
 #define NVME_DEFAULT_KATO      5
 #define NVME_KATO_GRACE                10
 
+#ifdef CONFIG_ARCH_NO_SG_CHAIN
+#define  NVME_INLINE_SG_CNT  0
+#else
+#define  NVME_INLINE_SG_CNT  2
+#endif
+
 extern struct workqueue_struct *nvme_wq;
 extern struct workqueue_struct *nvme_reset_wq;
 extern struct workqueue_struct *nvme_delete_wq;
index dcaad58..365a2dd 100644 (file)
@@ -68,14 +68,14 @@ static int io_queue_depth = 1024;
 module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644);
 MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
 
-static int write_queues;
-module_param(write_queues, int, 0644);
+static unsigned int write_queues;
+module_param(write_queues, uint, 0644);
 MODULE_PARM_DESC(write_queues,
        "Number of queues to use for writes. If not set, reads and writes "
        "will share a queue set.");
 
-static int poll_queues;
-module_param(poll_queues, int, 0644);
+static unsigned int poll_queues;
+module_param(poll_queues, uint, 0644);
 MODULE_PARM_DESC(poll_queues, "Number of queues to use for polled IO.");
 
 struct nvme_dev;
@@ -176,7 +176,6 @@ struct nvme_queue {
        u16 sq_tail;
        u16 last_sq_tail;
        u16 cq_head;
-       u16 last_cq_head;
        u16 qid;
        u8 cq_phase;
        u8 sqes;
@@ -1026,10 +1025,7 @@ static irqreturn_t nvme_irq(int irq, void *data)
         * the irq handler, even if that was on another CPU.
         */
        rmb();
-       if (nvmeq->cq_head != nvmeq->last_cq_head)
-               ret = IRQ_HANDLED;
        nvme_process_cq(nvmeq, &start, &end, -1);
-       nvmeq->last_cq_head = nvmeq->cq_head;
        wmb();
 
        if (start != end) {
@@ -1549,7 +1545,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
        result = adapter_alloc_sq(dev, qid, nvmeq);
        if (result < 0)
                return result;
-       else if (result)
+       if (result)
                goto release_cq;
 
        nvmeq->cq_vector = vector;
@@ -2058,7 +2054,6 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                .priv           = dev,
        };
        unsigned int irq_queues, this_p_queues;
-       unsigned int nr_cpus = num_possible_cpus();
 
        /*
         * Poll queues don't need interrupts, but we need at least one IO
@@ -2069,10 +2064,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                this_p_queues = nr_io_queues - 1;
                irq_queues = 1;
        } else {
-               if (nr_cpus < nr_io_queues - this_p_queues)
-                       irq_queues = nr_cpus + 1;
-               else
-                       irq_queues = nr_io_queues - this_p_queues + 1;
+               irq_queues = nr_io_queues - this_p_queues + 1;
        }
        dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -3142,6 +3134,9 @@ static int __init nvme_init(void)
        BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
        BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2);
+
+       write_queues = min(write_queues, num_possible_cpus());
+       poll_queues = min(poll_queues, num_possible_cpus());
        return pci_register_driver(&nvme_driver);
 }
 
index dce5945..2a47c6c 100644 (file)
@@ -731,7 +731,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
                set->reserved_tags = 2; /* connect + keep-alive */
                set->numa_node = nctrl->numa_node;
                set->cmd_size = sizeof(struct nvme_rdma_request) +
-                       SG_CHUNK_SIZE * sizeof(struct scatterlist);
+                       NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
                set->driver_data = ctrl;
                set->nr_hw_queues = 1;
                set->timeout = ADMIN_TIMEOUT;
@@ -745,7 +745,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
                set->numa_node = nctrl->numa_node;
                set->flags = BLK_MQ_F_SHOULD_MERGE;
                set->cmd_size = sizeof(struct nvme_rdma_request) +
-                       SG_CHUNK_SIZE * sizeof(struct scatterlist);
+                       NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
                set->driver_data = ctrl;
                set->nr_hw_queues = nctrl->queue_count - 1;
                set->timeout = NVME_IO_TIMEOUT;
@@ -1160,7 +1160,7 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue,
        }
 
        ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq));
-       sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT);
 }
 
 static int nvme_rdma_set_sg_null(struct nvme_command *c)
@@ -1276,7 +1276,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
        req->sg_table.sgl = req->first_sgl;
        ret = sg_alloc_table_chained(&req->sg_table,
                        blk_rq_nr_phys_segments(rq), req->sg_table.sgl,
-                       SG_CHUNK_SIZE);
+                       NVME_INLINE_SG_CNT);
        if (ret)
                return -ENOMEM;
 
@@ -1314,7 +1314,7 @@ out:
 out_unmap_sg:
        ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq));
 out_free_table:
-       sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT);
        return ret;
 }
 
index b50b53d..1c50af6 100644 (file)
@@ -850,6 +850,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
 #define FCLOOP_DMABOUND_4G             0xFFFFFFFF
 
 static struct nvme_fc_port_template fctemplate = {
+       .module                 = THIS_MODULE,
        .localport_delete       = fcloop_localport_delete,
        .remoteport_delete      = fcloop_remoteport_delete,
        .create_queue           = fcloop_create_queue,
index a758bb3..4df4ebd 100644 (file)
@@ -76,7 +76,7 @@ static void nvme_loop_complete_rq(struct request *req)
 {
        struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req);
 
-       sg_free_table_chained(&iod->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&iod->sg_table, NVME_INLINE_SG_CNT);
        nvme_complete_rq(req);
 }
 
@@ -156,7 +156,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
                iod->sg_table.sgl = iod->first_sgl;
                if (sg_alloc_table_chained(&iod->sg_table,
                                blk_rq_nr_phys_segments(req),
-                               iod->sg_table.sgl, SG_CHUNK_SIZE)) {
+                               iod->sg_table.sgl, NVME_INLINE_SG_CNT)) {
                        nvme_cleanup_cmd(req);
                        return BLK_STS_RESOURCE;
                }
@@ -342,7 +342,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
        ctrl->admin_tag_set.reserved_tags = 2; /* connect + keep-alive */
        ctrl->admin_tag_set.numa_node = NUMA_NO_NODE;
        ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
-               SG_CHUNK_SIZE * sizeof(struct scatterlist);
+               NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
        ctrl->admin_tag_set.driver_data = ctrl;
        ctrl->admin_tag_set.nr_hw_queues = 1;
        ctrl->admin_tag_set.timeout = ADMIN_TIMEOUT;
@@ -516,7 +516,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
        ctrl->tag_set.numa_node = NUMA_NO_NODE;
        ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
        ctrl->tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
-               SG_CHUNK_SIZE * sizeof(struct scatterlist);
+               NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
        ctrl->tag_set.driver_data = ctrl;
        ctrl->tag_set.nr_hw_queues = ctrl->ctrl.queue_count - 1;
        ctrl->tag_set.timeout = NVME_IO_TIMEOUT;
index d93891a..3371e4a 100644 (file)
@@ -518,10 +518,11 @@ static int __init of_platform_default_populate_init(void)
 {
        struct device_node *node;
 
+       device_links_supplier_sync_state_pause();
+
        if (!of_have_populated_dt())
                return -ENODEV;
 
-       device_links_supplier_sync_state_pause();
        /*
         * Handle certain compatibles explicitly, since we don't want to create
         * platform_devices for every node in /reserved-memory with a
@@ -545,8 +546,7 @@ arch_initcall_sync(of_platform_default_populate_init);
 
 static int __init of_platform_sync_state_init(void)
 {
-       if (of_have_populated_dt())
-               device_links_supplier_sync_state_resume();
+       device_links_supplier_sync_state_resume();
        return 0;
 }
 late_initcall_sync(of_platform_sync_state_init);
index d9b63bf..94af6f5 100644 (file)
@@ -834,10 +834,12 @@ static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
        if (!entry)
                return -ENODEV;
 
+       /* store the register number offset to program RC io outbound ATU */
+       offset = size >> 20;
+
        size = resource_size(entry->res);
        pci_addr = entry->res->start - entry->offset;
 
-       offset = size >> 20;
        for (reg_no = 0; reg_no < (size >> 20); reg_no++) {
                err = rockchip_pcie_prog_ob_atu(rockchip,
                                                reg_no + 1 + offset,
index 773128f..d704ecc 100644 (file)
@@ -814,7 +814,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
        if (err) {
                dev_err(dev, "Error %d registering hotplug, PMU @%pa\n",
                        err, &res_0->start);
-               goto out_cpuhp_err;
+               return err;
        }
 
        err = perf_pmu_register(&smmu_pmu->pmu, name, -1);
@@ -833,8 +833,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
 
 out_unregister:
        cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
-out_cpuhp_err:
-       put_cpu();
        return err;
 }
 
index 3bfbf2f..df0ef69 100644 (file)
@@ -422,6 +422,7 @@ config PINCTRL_TB10X
 
 config PINCTRL_EQUILIBRIUM
        tristate "Generic pinctrl and GPIO driver for Intel Lightning Mountain SoC"
+       depends on OF && HAS_IOMEM
        select PINMUX
        select PINCONF
        select GPIOLIB
index c6800d2..bb07024 100644 (file)
@@ -1088,60 +1088,52 @@ SSSF_PIN_DECL(AF15, GPIOV7, LPCSMI, SIG_DESC_SET(SCU434, 15));
 
 #define AB7 176
 SIG_EXPR_LIST_DECL_SESG(AB7, LAD0, LPC, SIG_DESC_SET(SCU434, 16),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16));
 PIN_DECL_2(AB7, GPIOW0, LAD0, ESPID0);
 
 #define AB8 177
 SIG_EXPR_LIST_DECL_SESG(AB8, LAD1, LPC, SIG_DESC_SET(SCU434, 17),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17));
 PIN_DECL_2(AB8, GPIOW1, LAD1, ESPID1);
 
 #define AC8 178
 SIG_EXPR_LIST_DECL_SESG(AC8, LAD2, LPC, SIG_DESC_SET(SCU434, 18),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18));
 PIN_DECL_2(AC8, GPIOW2, LAD2, ESPID2);
 
 #define AC7 179
 SIG_EXPR_LIST_DECL_SESG(AC7, LAD3, LPC, SIG_DESC_SET(SCU434, 19),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19));
 PIN_DECL_2(AC7, GPIOW3, LAD3, ESPID3);
 
 #define AE7 180
 SIG_EXPR_LIST_DECL_SESG(AE7, LCLK, LPC, SIG_DESC_SET(SCU434, 20),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20));
 PIN_DECL_2(AE7, GPIOW4, LCLK, ESPICK);
 
 #define AF7 181
 SIG_EXPR_LIST_DECL_SESG(AF7, LFRAME, LPC, SIG_DESC_SET(SCU434, 21),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21));
 PIN_DECL_2(AF7, GPIOW5, LFRAME, ESPICS);
 
 #define AD7 182
 SIG_EXPR_LIST_DECL_SESG(AD7, LSIRQ, LSIRQ, SIG_DESC_SET(SCU434, 22),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22));
 PIN_DECL_2(AD7, GPIOW6, LSIRQ, ESPIALT);
 FUNC_GROUP_DECL(LSIRQ, AD7);
 FUNC_GROUP_DECL(ESPIALT, AD7);
 
 #define AD8 183
 SIG_EXPR_LIST_DECL_SESG(AD8, LPCRST, LPC, SIG_DESC_SET(SCU434, 23),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23));
 PIN_DECL_2(AD8, GPIOW7, LPCRST, ESPIRST);
 
 FUNC_GROUP_DECL(LPC, AB7, AB8, AC8, AC7, AE7, AF7, AD8);
index 9ffb222..55141d5 100644 (file)
@@ -110,7 +110,6 @@ struct byt_gpio {
        struct platform_device *pdev;
        struct pinctrl_dev *pctl_dev;
        struct pinctrl_desc pctl_desc;
-       raw_spinlock_t lock;
        const struct intel_pinctrl_soc_data *soc_data;
        struct intel_community *communities_copy;
        struct byt_gpio_pin_context *saved_context;
@@ -494,34 +493,34 @@ static const struct intel_pinctrl_soc_data byt_sus_soc_data = {
 };
 
 static const struct pinctrl_pin_desc byt_ncore_pins[] = {
-       PINCTRL_PIN(0, "GPIO_NCORE0"),
-       PINCTRL_PIN(1, "GPIO_NCORE1"),
-       PINCTRL_PIN(2, "GPIO_NCORE2"),
-       PINCTRL_PIN(3, "GPIO_NCORE3"),
-       PINCTRL_PIN(4, "GPIO_NCORE4"),
-       PINCTRL_PIN(5, "GPIO_NCORE5"),
-       PINCTRL_PIN(6, "GPIO_NCORE6"),
-       PINCTRL_PIN(7, "GPIO_NCORE7"),
-       PINCTRL_PIN(8, "GPIO_NCORE8"),
-       PINCTRL_PIN(9, "GPIO_NCORE9"),
-       PINCTRL_PIN(10, "GPIO_NCORE10"),
-       PINCTRL_PIN(11, "GPIO_NCORE11"),
-       PINCTRL_PIN(12, "GPIO_NCORE12"),
-       PINCTRL_PIN(13, "GPIO_NCORE13"),
-       PINCTRL_PIN(14, "GPIO_NCORE14"),
-       PINCTRL_PIN(15, "GPIO_NCORE15"),
-       PINCTRL_PIN(16, "GPIO_NCORE16"),
-       PINCTRL_PIN(17, "GPIO_NCORE17"),
-       PINCTRL_PIN(18, "GPIO_NCORE18"),
-       PINCTRL_PIN(19, "GPIO_NCORE19"),
-       PINCTRL_PIN(20, "GPIO_NCORE20"),
-       PINCTRL_PIN(21, "GPIO_NCORE21"),
-       PINCTRL_PIN(22, "GPIO_NCORE22"),
-       PINCTRL_PIN(23, "GPIO_NCORE23"),
-       PINCTRL_PIN(24, "GPIO_NCORE24"),
-       PINCTRL_PIN(25, "GPIO_NCORE25"),
-       PINCTRL_PIN(26, "GPIO_NCORE26"),
-       PINCTRL_PIN(27, "GPIO_NCORE27"),
+       PINCTRL_PIN(0, "HV_DDI0_HPD"),
+       PINCTRL_PIN(1, "HV_DDI0_DDC_SDA"),
+       PINCTRL_PIN(2, "HV_DDI0_DDC_SCL"),
+       PINCTRL_PIN(3, "PANEL0_VDDEN"),
+       PINCTRL_PIN(4, "PANEL0_BKLTEN"),
+       PINCTRL_PIN(5, "PANEL0_BKLTCTL"),
+       PINCTRL_PIN(6, "HV_DDI1_HPD"),
+       PINCTRL_PIN(7, "HV_DDI1_DDC_SDA"),
+       PINCTRL_PIN(8, "HV_DDI1_DDC_SCL"),
+       PINCTRL_PIN(9, "PANEL1_VDDEN"),
+       PINCTRL_PIN(10, "PANEL1_BKLTEN"),
+       PINCTRL_PIN(11, "PANEL1_BKLTCTL"),
+       PINCTRL_PIN(12, "GP_INTD_DSI_TE1"),
+       PINCTRL_PIN(13, "HV_DDI2_DDC_SDA"),
+       PINCTRL_PIN(14, "HV_DDI2_DDC_SCL"),
+       PINCTRL_PIN(15, "GP_CAMERASB00"),
+       PINCTRL_PIN(16, "GP_CAMERASB01"),
+       PINCTRL_PIN(17, "GP_CAMERASB02"),
+       PINCTRL_PIN(18, "GP_CAMERASB03"),
+       PINCTRL_PIN(19, "GP_CAMERASB04"),
+       PINCTRL_PIN(20, "GP_CAMERASB05"),
+       PINCTRL_PIN(21, "GP_CAMERASB06"),
+       PINCTRL_PIN(22, "GP_CAMERASB07"),
+       PINCTRL_PIN(23, "GP_CAMERASB08"),
+       PINCTRL_PIN(24, "GP_CAMERASB09"),
+       PINCTRL_PIN(25, "GP_CAMERASB10"),
+       PINCTRL_PIN(26, "GP_CAMERASB11"),
+       PINCTRL_PIN(27, "GP_INTD_DSI_TE2"),
 };
 
 static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
@@ -549,6 +548,8 @@ static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
        NULL
 };
 
+static DEFINE_RAW_SPINLOCK(byt_lock);
+
 static struct intel_community *byt_get_community(struct byt_gpio *vg,
                                                 unsigned int pin)
 {
@@ -658,7 +659,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
        unsigned long flags;
        int i;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        for (i = 0; i < group.npins; i++) {
                void __iomem *padcfg0;
@@ -678,7 +679,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
                writel(value, padcfg0);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static void byt_set_group_mixed_mux(struct byt_gpio *vg,
@@ -688,7 +689,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
        unsigned long flags;
        int i;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        for (i = 0; i < group.npins; i++) {
                void __iomem *padcfg0;
@@ -708,7 +709,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
                writel(value, padcfg0);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
@@ -749,11 +750,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
        unsigned long flags;
        u32 value;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
        value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
        writel(value, reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
@@ -765,7 +766,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
        u32 value, gpio_mux;
        unsigned long flags;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        /*
         * In most cases, func pin mux 000 means GPIO function.
@@ -787,7 +788,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
                         "pin %u forcibly re-configured as GPIO\n", offset);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        pm_runtime_get(&vg->pdev->dev);
 
@@ -815,7 +816,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
        unsigned long flags;
        u32 value;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        value = readl(val_reg);
        value &= ~BYT_DIR_MASK;
@@ -832,7 +833,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
                     "Potential Error: Setting GPIO with direct_irq_en to output");
        writel(value, val_reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return 0;
 }
@@ -901,11 +902,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
        u32 conf, pull, val, debounce;
        u16 arg = 0;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        conf = readl(conf_reg);
        pull = conf & BYT_PULL_ASSIGN_MASK;
        val = readl(val_reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        switch (param) {
        case PIN_CONFIG_BIAS_DISABLE:
@@ -932,9 +933,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
                if (!(conf & BYT_DEBOUNCE_EN))
                        return -EINVAL;
 
-               raw_spin_lock_irqsave(&vg->lock, flags);
+               raw_spin_lock_irqsave(&byt_lock, flags);
                debounce = readl(db_reg);
-               raw_spin_unlock_irqrestore(&vg->lock, flags);
+               raw_spin_unlock_irqrestore(&byt_lock, flags);
 
                switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
                case BYT_DEBOUNCE_PULSE_375US:
@@ -986,7 +987,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
        u32 conf, val, debounce;
        int i, ret = 0;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        conf = readl(conf_reg);
        val = readl(val_reg);
@@ -1094,7 +1095,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
        if (!ret)
                writel(conf, conf_reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return ret;
 }
@@ -1119,9 +1120,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
        unsigned long flags;
        u32 val;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        val = readl(reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return !!(val & BYT_LEVEL);
 }
@@ -1136,13 +1137,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
        if (!reg)
                return;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        old_val = readl(reg);
        if (value)
                writel(old_val | BYT_LEVEL, reg);
        else
                writel(old_val & ~BYT_LEVEL, reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
@@ -1155,9 +1156,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
        if (!reg)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        if (!(value & BYT_OUTPUT_EN))
                return 0;
@@ -1200,14 +1201,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                const char *label;
                unsigned int pin;
 
-               raw_spin_lock_irqsave(&vg->lock, flags);
+               raw_spin_lock_irqsave(&byt_lock, flags);
                pin = vg->soc_data->pins[i].number;
                reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
                if (!reg) {
                        seq_printf(s,
                                   "Could not retrieve pin %i conf0 reg\n",
                                   pin);
-                       raw_spin_unlock_irqrestore(&vg->lock, flags);
+                       raw_spin_unlock_irqrestore(&byt_lock, flags);
                        continue;
                }
                conf0 = readl(reg);
@@ -1216,11 +1217,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                if (!reg) {
                        seq_printf(s,
                                   "Could not retrieve pin %i val reg\n", pin);
-                       raw_spin_unlock_irqrestore(&vg->lock, flags);
+                       raw_spin_unlock_irqrestore(&byt_lock, flags);
                        continue;
                }
                val = readl(reg);
-               raw_spin_unlock_irqrestore(&vg->lock, flags);
+               raw_spin_unlock_irqrestore(&byt_lock, flags);
 
                comm = byt_get_community(vg, pin);
                if (!comm) {
@@ -1304,9 +1305,9 @@ static void byt_irq_ack(struct irq_data *d)
        if (!reg)
                return;
 
-       raw_spin_lock(&vg->lock);
+       raw_spin_lock(&byt_lock);
        writel(BIT(offset % 32), reg);
-       raw_spin_unlock(&vg->lock);
+       raw_spin_unlock(&byt_lock);
 }
 
 static void byt_irq_mask(struct irq_data *d)
@@ -1330,7 +1331,7 @@ static void byt_irq_unmask(struct irq_data *d)
        if (!reg)
                return;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
 
        switch (irqd_get_trigger_type(d)) {
@@ -1353,7 +1354,7 @@ static void byt_irq_unmask(struct irq_data *d)
 
        writel(value, reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_irq_type(struct irq_data *d, unsigned int type)
@@ -1367,7 +1368,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
        if (!reg || offset >= vg->chip.ngpio)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
 
        WARN(value & BYT_DIRECT_IRQ_EN,
@@ -1389,7 +1390,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
        else if (type & IRQ_TYPE_LEVEL_MASK)
                irq_set_handler_locked(d, handle_level_irq);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return 0;
 }
@@ -1425,9 +1426,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
                        continue;
                }
 
-               raw_spin_lock(&vg->lock);
+               raw_spin_lock(&byt_lock);
                pending = readl(reg);
-               raw_spin_unlock(&vg->lock);
+               raw_spin_unlock(&byt_lock);
                for_each_set_bit(pin, &pending, 32) {
                        virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
                        generic_handle_irq(virq);
@@ -1450,9 +1451,9 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip,
         */
 }
 
-static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
+static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
 {
-       struct gpio_chip *gc = &vg->chip;
+       struct byt_gpio *vg = gpiochip_get_data(chip);
        struct device *dev = &vg->pdev->dev;
        void __iomem *reg;
        u32 base, value;
@@ -1476,7 +1477,7 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 
                value = readl(reg);
                if (value & BYT_DIRECT_IRQ_EN) {
-                       clear_bit(i, gc->irq.valid_mask);
+                       clear_bit(i, chip->irq.valid_mask);
                        dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
                } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
                        byt_gpio_clear_triggering(vg, i);
@@ -1504,6 +1505,21 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
                                "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
                                base / 32, value);
        }
+
+       return 0;
+}
+
+static int byt_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+       struct byt_gpio *vg = gpiochip_get_data(chip);
+       struct device *dev = &vg->pdev->dev;
+       int ret;
+
+       ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc_data->npins);
+       if (ret)
+               dev_err(dev, "failed to add GPIO pin range\n");
+
+       return ret;
 }
 
 static int byt_gpio_probe(struct byt_gpio *vg)
@@ -1518,6 +1534,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
        gc->label       = dev_name(&vg->pdev->dev);
        gc->base        = -1;
        gc->can_sleep   = false;
+       gc->add_pin_ranges = byt_gpio_add_pin_ranges;
        gc->parent      = &vg->pdev->dev;
        gc->ngpio       = vg->soc_data->npins;
        gc->irq.init_valid_mask = byt_init_irq_valid_mask;
@@ -1528,33 +1545,30 @@ static int byt_gpio_probe(struct byt_gpio *vg)
        if (!vg->saved_context)
                return -ENOMEM;
 #endif
-       ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
-       if (ret) {
-               dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
-               return ret;
-       }
-
-       ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
-                                    0, 0, vg->soc_data->npins);
-       if (ret) {
-               dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
-               return ret;
-       }
 
        /* set up interrupts  */
        irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
        if (irq_rc && irq_rc->start) {
-               byt_gpio_irq_init_hw(vg);
-               ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
-                                          handle_bad_irq, IRQ_TYPE_NONE);
-               if (ret) {
-                       dev_err(&vg->pdev->dev, "failed to add irqchip\n");
-                       return ret;
-               }
+               struct gpio_irq_chip *girq;
+
+               girq = &gc->irq;
+               girq->chip = &byt_irqchip;
+               girq->init_hw = byt_gpio_irq_init_hw;
+               girq->parent_handler = byt_gpio_irq_handler;
+               girq->num_parents = 1;
+               girq->parents = devm_kcalloc(&vg->pdev->dev, girq->num_parents,
+                                            sizeof(*girq->parents), GFP_KERNEL);
+               if (!girq->parents)
+                       return -ENOMEM;
+               girq->parents[0] = (unsigned int)irq_rc->start;
+               girq->default_type = IRQ_TYPE_NONE;
+               girq->handler = handle_bad_irq;
+       }
 
-               gpiochip_set_chained_irqchip(gc, &byt_irqchip,
-                                            (unsigned)irq_rc->start,
-                                            byt_gpio_irq_handler);
+       ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
+       if (ret) {
+               dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
+               return ret;
        }
 
        return ret;
@@ -1638,8 +1652,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
                return PTR_ERR(vg->pctl_dev);
        }
 
-       raw_spin_lock_init(&vg->lock);
-
        ret = byt_gpio_probe(vg);
        if (ret)
                return ret;
@@ -1654,8 +1666,11 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
 static int byt_gpio_suspend(struct device *dev)
 {
        struct byt_gpio *vg = dev_get_drvdata(dev);
+       unsigned long flags;
        int i;
 
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
        for (i = 0; i < vg->soc_data->npins; i++) {
                void __iomem *reg;
                u32 value;
@@ -1676,14 +1691,18 @@ static int byt_gpio_suspend(struct device *dev)
                vg->saved_context[i].val = value;
        }
 
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
        return 0;
 }
 
 static int byt_gpio_resume(struct device *dev)
 {
        struct byt_gpio *vg = dev_get_drvdata(dev);
+       unsigned long flags;
        int i;
 
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
        for (i = 0; i < vg->soc_data->npins; i++) {
                void __iomem *reg;
                u32 value;
@@ -1721,6 +1740,7 @@ static int byt_gpio_resume(struct device *dev)
                }
        }
 
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
        return 0;
 }
 #endif
index 582fa8a..60527b9 100644 (file)
@@ -149,6 +149,7 @@ struct chv_pin_context {
  * @chip: GPIO chip in this pin controller
  * @irqchip: IRQ chip in this pin controller
  * @regs: MMIO registers
+ * @irq: Our parent irq
  * @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
  *             offset (in GPIO number space)
  * @community: Community this pinctrl instance represents
@@ -165,6 +166,7 @@ struct chv_pinctrl {
        struct gpio_chip chip;
        struct irq_chip irqchip;
        void __iomem *regs;
+       unsigned int irq;
        unsigned int intr_lines[16];
        const struct chv_community *community;
        u32 saved_intmask;
@@ -1555,39 +1557,9 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip,
        }
 }
 
-static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
+static int chv_gpio_irq_init_hw(struct gpio_chip *chip)
 {
-       const struct chv_gpio_pinrange *range;
-       struct gpio_chip *chip = &pctrl->chip;
-       bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
-       const struct chv_community *community = pctrl->community;
-       int ret, i, irq_base;
-
-       *chip = chv_gpio_chip;
-
-       chip->ngpio = community->pins[community->npins - 1].number + 1;
-       chip->label = dev_name(pctrl->dev);
-       chip->parent = pctrl->dev;
-       chip->base = -1;
-       if (need_valid_mask)
-               chip->irq.init_valid_mask = chv_init_irq_valid_mask;
-
-       ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
-       if (ret) {
-               dev_err(pctrl->dev, "Failed to register gpiochip\n");
-               return ret;
-       }
-
-       for (i = 0; i < community->ngpio_ranges; i++) {
-               range = &community->gpio_ranges[i];
-               ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
-                                            range->base, range->base,
-                                            range->npins);
-               if (ret) {
-                       dev_err(pctrl->dev, "failed to add GPIO pin range\n");
-                       return ret;
-               }
-       }
+       struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
 
        /*
         * The same set of machines in chv_no_valid_mask[] have incorrectly
@@ -1596,7 +1568,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
         *
         * See also https://bugzilla.kernel.org/show_bug.cgi?id=197953.
         */
-       if (!need_valid_mask) {
+       if (!pctrl->chip.irq.init_valid_mask) {
                /*
                 * Mask all interrupts the community is able to generate
                 * but leave the ones that can only generate GPEs unmasked.
@@ -1608,15 +1580,47 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
        /* Clear all interrupts */
        chv_writel(0xffff, pctrl->regs + CHV_INTSTAT);
 
-       if (!need_valid_mask) {
-               irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0,
-                                               community->npins, NUMA_NO_NODE);
-               if (irq_base < 0) {
-                       dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n");
-                       return irq_base;
+       return 0;
+}
+
+static int chv_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+       struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
+       const struct chv_community *community = pctrl->community;
+       const struct chv_gpio_pinrange *range;
+       int ret, i;
+
+       for (i = 0; i < community->ngpio_ranges; i++) {
+               range = &community->gpio_ranges[i];
+               ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
+                                            range->base, range->base,
+                                            range->npins);
+               if (ret) {
+                       dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+                       return ret;
                }
        }
 
+       return 0;
+}
+
+static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
+{
+       const struct chv_gpio_pinrange *range;
+       struct gpio_chip *chip = &pctrl->chip;
+       bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
+       const struct chv_community *community = pctrl->community;
+       int ret, i, irq_base;
+
+       *chip = chv_gpio_chip;
+
+       chip->ngpio = community->pins[community->npins - 1].number + 1;
+       chip->label = dev_name(pctrl->dev);
+       chip->add_pin_ranges = chv_gpio_add_pin_ranges;
+       chip->parent = pctrl->dev;
+       chip->base = -1;
+
+       pctrl->irq = irq;
        pctrl->irqchip.name = "chv-gpio";
        pctrl->irqchip.irq_startup = chv_gpio_irq_startup;
        pctrl->irqchip.irq_ack = chv_gpio_irq_ack;
@@ -1625,10 +1629,27 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
        pctrl->irqchip.irq_set_type = chv_gpio_irq_type;
        pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE;
 
-       ret = gpiochip_irqchip_add(chip, &pctrl->irqchip, 0,
-                                  handle_bad_irq, IRQ_TYPE_NONE);
+       chip->irq.chip = &pctrl->irqchip;
+       chip->irq.init_hw = chv_gpio_irq_init_hw;
+       chip->irq.parent_handler = chv_gpio_irq_handler;
+       chip->irq.num_parents = 1;
+       chip->irq.parents = &pctrl->irq;
+       chip->irq.default_type = IRQ_TYPE_NONE;
+       chip->irq.handler = handle_bad_irq;
+       if (need_valid_mask) {
+               chip->irq.init_valid_mask = chv_init_irq_valid_mask;
+       } else {
+               irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0,
+                                               community->npins, NUMA_NO_NODE);
+               if (irq_base < 0) {
+                       dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n");
+                       return irq_base;
+               }
+       }
+
+       ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
        if (ret) {
-               dev_err(pctrl->dev, "failed to add IRQ chip\n");
+               dev_err(pctrl->dev, "Failed to register gpiochip\n");
                return ret;
        }
 
@@ -1642,8 +1663,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
                }
        }
 
-       gpiochip_set_chained_irqchip(chip, &pctrl->irqchip, irq,
-                                    chv_gpio_irq_handler);
        return 0;
 }
 
index 24e0e2e..369e043 100644 (file)
@@ -1809,7 +1809,7 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
 static void ingenic_set_output_level(struct ingenic_pinctrl *jzpc,
                                     unsigned int pin, bool high)
 {
-       if (jzpc->version >= ID_JZ4770)
+       if (jzpc->version >= ID_JZ4760)
                ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, high);
        else
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DATA, high);
index e914f6e..9503ddf 100644 (file)
@@ -85,7 +85,7 @@ bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
 
        /* Can't inspect pin, assume it can be used */
-       if (!desc)
+       if (!desc || !ops)
                return true;
 
        if (ops->strict && desc->mux_usecount)
index 61753b6..5d21c6a 100644 (file)
@@ -309,7 +309,7 @@ static struct platform_driver mlxbf_bootctl_driver = {
        .probe = mlxbf_bootctl_probe,
        .driver = {
                .name = "mlxbf-bootctl",
-               .groups = mlxbf_bootctl_groups,
+               .dev_groups = mlxbf_bootctl_groups,
                .acpi_match_table = mlxbf_bootctl_acpi_ids,
        }
 };
index 9579a70..a881b70 100644 (file)
@@ -300,7 +300,7 @@ static int __init hp_wmi_bios_2008_later(void)
 
 static int __init hp_wmi_bios_2009_later(void)
 {
-       int state = 0;
+       u8 state[128];
        int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
                                       sizeof(state), sizeof(state));
        if (!ret)
index 48b112b..9b11ef1 100644 (file)
@@ -2,7 +2,7 @@
 
 /*
  * PC-Engines APUv2/APUv3 board platform driver
- * for gpio buttons and LEDs
+ * for GPIO buttons and LEDs
  *
  * Copyright (C) 2018 metux IT consult
  * Author: Enrico Weigelt <info@metux.net>
 
 /*
  * NOTE: this driver only supports APUv2/3 - not APUv1, as this one
- * has completely different register layouts
+ * has completely different register layouts.
  */
 
-/* register mappings */
+/* Register mappings */
 #define APU2_GPIO_REG_LED1             AMD_FCH_GPIO_REG_GPIO57
 #define APU2_GPIO_REG_LED2             AMD_FCH_GPIO_REG_GPIO58
 #define APU2_GPIO_REG_LED3             AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
@@ -35,7 +35,7 @@
 #define APU2_GPIO_REG_MPCIE2           AMD_FCH_GPIO_REG_GPIO59_DEVSLP0
 #define APU2_GPIO_REG_MPCIE3           AMD_FCH_GPIO_REG_GPIO51
 
-/* order in which the gpio lines are defined in the register list */
+/* Order in which the GPIO lines are defined in the register list */
 #define APU2_GPIO_LINE_LED1            0
 #define APU2_GPIO_LINE_LED2            1
 #define APU2_GPIO_LINE_LED3            2
@@ -44,7 +44,7 @@
 #define APU2_GPIO_LINE_MPCIE2          5
 #define APU2_GPIO_LINE_MPCIE3          6
 
-/* gpio device */
+/* GPIO device */
 
 static int apu2_gpio_regs[] = {
        [APU2_GPIO_LINE_LED1]           = APU2_GPIO_REG_LED1,
@@ -72,7 +72,7 @@ static const struct amd_fch_gpio_pdata board_apu2 = {
        .gpio_names     = apu2_gpio_names,
 };
 
-/* gpio leds device */
+/* GPIO LEDs device */
 
 static const struct gpio_led apu2_leds[] = {
        { .name = "apu:green:1" },
@@ -95,12 +95,12 @@ static struct gpiod_lookup_table gpios_led_table = {
                                NULL, 1, GPIO_ACTIVE_LOW),
                GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
                                NULL, 2, GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_REG_SIMSWAP,
+               GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_SIMSWAP,
                                NULL, 3, GPIO_ACTIVE_LOW),
        }
 };
 
-/* gpio keyboard device */
+/* GPIO keyboard device */
 
 static struct gpio_keys_button apu2_keys_buttons[] = {
        {
@@ -129,12 +129,12 @@ static struct gpiod_lookup_table gpios_key_table = {
        }
 };
 
-/* board setup */
+/* Board setup */
 
-/* note: matching works on string prefix, so "apu2" must come before "apu" */
+/* Note: matching works on string prefix, so "apu2" must come before "apu" */
 static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
 
-       /* APU2 w/ legacy bios < 4.0.8 */
+       /* APU2 w/ legacy BIOS < 4.0.8 */
        {
                .ident          = "apu2",
                .matches        = {
@@ -143,7 +143,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data    = (void *)&board_apu2,
        },
-       /* APU2 w/ legacy bios >= 4.0.8 */
+       /* APU2 w/ legacy BIOS >= 4.0.8 */
        {
                .ident          = "apu2",
                .matches        = {
@@ -152,7 +152,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data    = (void *)&board_apu2,
        },
-       /* APU2 w/ maainline bios */
+       /* APU2 w/ mainline BIOS */
        {
                .ident          = "apu2",
                .matches        = {
@@ -162,7 +162,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                .driver_data    = (void *)&board_apu2,
        },
 
-       /* APU3 w/ legacy bios < 4.0.8 */
+       /* APU3 w/ legacy BIOS < 4.0.8 */
        {
                .ident          = "apu3",
                .matches        = {
@@ -171,7 +171,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
-       /* APU3 w/ legacy bios >= 4.0.8 */
+       /* APU3 w/ legacy BIOS >= 4.0.8 */
        {
                .ident       = "apu3",
                .matches     = {
@@ -180,7 +180,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
-       /* APU3 w/ mainline bios */
+       /* APU3 w/ mainline BIOS */
        {
                .ident       = "apu3",
                .matches     = {
@@ -189,6 +189,33 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
+       /* APU4 w/ legacy BIOS < 4.0.8 */
+       {
+               .ident        = "apu4",
+               .matches    = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "APU4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
+       /* APU4 w/ legacy BIOS >= 4.0.8 */
+       {
+               .ident       = "apu4",
+               .matches     = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "apu4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
+       /* APU4 w/ mainline BIOS */
+       {
+               .ident       = "apu4",
+               .matches     = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
        {}
 };
 
@@ -223,7 +250,7 @@ static int __init apu_board_init(void)
 
        id = dmi_first_match(apu_gpio_dmi_table);
        if (!id) {
-               pr_err("failed to detect apu board via dmi\n");
+               pr_err("failed to detect APU board via DMI\n");
                return -ENODEV;
        }
 
@@ -262,7 +289,7 @@ module_init(apu_board_init);
 module_exit(apu_board_exit);
 
 MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
-MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LED/keys driver");
+MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LEDs/keys driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
 MODULE_ALIAS("platform:pcengines-apuv2");
index 07d1b91..52ef141 100644 (file)
@@ -429,6 +429,14 @@ static const struct dmi_system_id critclk_systems[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "6AV7882-0"),
                },
        },
+       {
+               .ident = "CONNECT X300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "A5E45074588"),
+               },
+       },
+
        { /*sentinel*/ }
 };
 
index 679ad3d..03d79fe 100644 (file)
@@ -1198,6 +1198,10 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
                        return -EINVAL;
                }
 
+               /* no need to loop voltages if range is continuous */
+               if (rdev->desc->continuous_voltage_range)
+                       return 0;
+
                /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
                for (i = 0; i < count; i++) {
                        int     value;
@@ -1938,8 +1942,8 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
        regulator = create_regulator(rdev, dev, id);
        if (regulator == NULL) {
                regulator = ERR_PTR(-ENOMEM);
-               put_device(&rdev->dev);
                module_put(rdev->owner);
+               put_device(&rdev->dev);
                return regulator;
        }
 
@@ -2063,13 +2067,13 @@ static void _regulator_put(struct regulator *regulator)
 
        rdev->open_count--;
        rdev->exclusive = 0;
-       put_device(&rdev->dev);
        regulator_unlock(rdev);
 
        kfree_const(regulator->supply_name);
        kfree(regulator);
 
        module_put(rdev->owner);
+       put_device(&rdev->dev);
 }
 
 /**
@@ -5002,6 +5006,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
        struct regulator_dev *rdev;
        bool dangling_cfg_gpiod = false;
        bool dangling_of_gpiod = false;
+       bool reg_device_fail = false;
        struct device *dev;
        int ret, i;
 
@@ -5187,7 +5192,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
        dev_set_drvdata(&rdev->dev, rdev);
        ret = device_register(&rdev->dev);
        if (ret != 0) {
-               put_device(&rdev->dev);
+               reg_device_fail = true;
                goto unset_supplies;
        }
 
@@ -5218,7 +5223,10 @@ wash:
 clean:
        if (dangling_of_gpiod)
                gpiod_put(config->ena_gpiod);
-       kfree(rdev);
+       if (reg_device_fail)
+               put_device(&rdev->dev);
+       else
+               kfree(rdev);
        kfree(config);
 rinse:
        if (dangling_cfg_gpiod)
index e57fc91..ac89a41 100644 (file)
@@ -386,9 +386,16 @@ static int max77650_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id max77650_regulator_of_match[] = {
+       { .compatible = "maxim,max77650-regulator" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
+
 static struct platform_driver max77650_regulator_driver = {
        .driver = {
                .name = "max77650-regulator",
+               .of_match_table = max77650_regulator_of_match,
        },
        .probe = max77650_regulator_probe,
 };
index 4a91be0..5c12d57 100644 (file)
@@ -148,6 +148,7 @@ static struct platform_driver rn5t618_regulator_driver = {
 
 module_platform_driver(rn5t618_regulator_driver);
 
+MODULE_ALIAS("platform:rn5t618-regulator");
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 MODULE_DESCRIPTION("RN5T618 regulator driver");
 MODULE_LICENSE("GPL v2");
index bdc0773..12d6b8d 100644 (file)
@@ -588,7 +588,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                if (of_property_read_u32(reg_np, "op_mode",
                                &rmode->mode)) {
                        dev_warn(iodev->dev,
-                               "no op_mode property property at %pOF\n",
+                               "no op_mode property at %pOF\n",
                                reg_np);
 
                        rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
index ca1d491..7597c70 100644 (file)
@@ -787,7 +787,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
                return ERR_PTR(-ENOMEM);
 
        rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
-       if (!IS_ERR(rstc)) {
+       if (!IS_ERR_OR_NULL(rstc)) {
                *ptr = rstc;
                devres_add(dev, ptr);
        } else {
@@ -861,8 +861,7 @@ static int of_reset_control_get_count(struct device_node *node)
  * @acquired: only one reset control may be acquired for a given controller
  *            and ID
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
@@ -915,8 +914,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get);
  * that just have to be asserted or deasserted, without any
  * requirements on the order.
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
@@ -930,7 +928,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
                return ERR_PTR(-ENOMEM);
 
        rstc = of_reset_control_array_get(dev->of_node, shared, optional, true);
-       if (IS_ERR(rstc)) {
+       if (IS_ERR_OR_NULL(rstc)) {
                devres_free(devres);
                return rstc;
        }
index a608f44..f213264 100644 (file)
@@ -91,12 +91,6 @@ static int brcmstb_reset_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!IS_ALIGNED(res->start, SW_INIT_BANK_SIZE) ||
-           !IS_ALIGNED(resource_size(res), SW_INIT_BANK_SIZE)) {
-               dev_err(kdev, "incorrect register range\n");
-               return -EINVAL;
-       }
-
        priv->base = devm_ioremap_resource(kdev, res);
        if (IS_ERR(priv->base))
                return PTR_ERR(priv->base);
index b9a2349..33a62a6 100644 (file)
@@ -4779,7 +4779,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 2, "qdioest");
 
-       qib_param_field = kzalloc(FIELD_SIZEOF(struct qib, parm), GFP_KERNEL);
+       qib_param_field = kzalloc(sizeof_field(struct qib, parm), GFP_KERNEL);
        if (!qib_param_field) {
                rc =  -ENOMEM;
                goto out_free_nothing;
index 88f4dc1..c1ecce9 100644 (file)
@@ -421,7 +421,7 @@ struct qeth_ipacmd_setassparms {
        } data;
 } __attribute__ ((packed));
 
-#define SETASS_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setassparms,\
+#define SETASS_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setassparms,\
                                               data.field)
 
 /* SETRTG IPA Command:    ****************************************************/
@@ -535,7 +535,7 @@ struct qeth_ipacmd_setadpparms {
        } data;
 } __attribute__ ((packed));
 
-#define SETADP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setadpparms,\
+#define SETADP_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setadpparms,\
                                               data.field)
 
 /* CREATE_ADDR IPA Command:    ***********************************************/
@@ -648,7 +648,7 @@ struct qeth_ipacmd_vnicc {
        } data;
 };
 
-#define VNICC_DATA_SIZEOF(field)       FIELD_SIZEOF(struct qeth_ipacmd_vnicc,\
+#define VNICC_DATA_SIZEOF(field)       sizeof_field(struct qeth_ipacmd_vnicc,\
                                                     data.field)
 
 /* SETBRIDGEPORT IPA Command:   *********************************************/
@@ -729,7 +729,7 @@ struct qeth_ipacmd_setbridgeport {
        } data;
 } __packed;
 
-#define SBP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setbridgeport,\
+#define SBP_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setbridgeport,\
                                             data.field)
 
 /* ADDRESS_CHANGE_NOTIFICATION adapter-initiated "command" *******************/
@@ -790,7 +790,7 @@ struct qeth_ipa_cmd {
        } data;
 } __attribute__ ((packed));
 
-#define IPA_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipa_cmd, data.field)
+#define IPA_DATA_SIZEOF(field) sizeof_field(struct qeth_ipa_cmd, data.field)
 
 /*
  * special command for ARP processing.
index e36608c..33dbc05 100644 (file)
@@ -535,7 +535,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        if ((le32_to_cpu(get_name_reply->status) == CT_OK)
         && (get_name_reply->data[0] != '\0')) {
                char *sp = get_name_reply->data;
-               int data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+               int data_size = sizeof_field(struct aac_get_name_resp, data);
 
                sp[data_size - 1] = '\0';
                while (*sp == ' ')
@@ -574,7 +574,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
-       data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+       data_size = sizeof_field(struct aac_get_name_resp, data);
 
        cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
 
index 063dccc..5f9f0b1 100644 (file)
@@ -1300,7 +1300,7 @@ struct be_cmd_get_port_name {
 
 /* Returns the number of items in the field array. */
 #define BE_NUMBER_OF_FIELD(_type_, _field_)    \
-       (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
+       (sizeof_field(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
 
 /**
  * Different types of iSCSI completions to host driver for both initiator
index 0d044c1..c4e4b01 100644 (file)
@@ -2746,7 +2746,7 @@ static int __init libcxgbi_init_module(void)
 {
        pr_info("%s", version);
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+       BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) <
                     sizeof(struct cxgbi_skb_cb));
        return 0;
 }
index ebd47c0..70b99c0 100644 (file)
@@ -1945,7 +1945,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 
        ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
 
-       spin_lock(&session->frwd_lock);
+       spin_lock_bh(&session->frwd_lock);
        task = (struct iscsi_task *)sc->SCp.ptr;
        if (!task) {
                /*
@@ -2072,7 +2072,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 done:
        if (task)
                task->last_timeout = jiffies;
-       spin_unlock(&session->frwd_lock);
+       spin_unlock_bh(&session->frwd_lock);
        ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
                     "timer reset" : "shutdown or nh");
        return rc;
index f47b4b2..d7302c2 100644 (file)
@@ -81,12 +81,21 @@ static int sas_get_port_device(struct asd_sas_port *port)
                else
                        dev->dev_type = SAS_SATA_DEV;
                dev->tproto = SAS_PROTOCOL_SATA;
-       } else {
+       } else if (port->oob_mode == SAS_OOB_MODE) {
                struct sas_identify_frame *id =
                        (struct sas_identify_frame *) dev->frame_rcvd;
                dev->dev_type = id->dev_type;
                dev->iproto = id->initiator_bits;
                dev->tproto = id->target_bits;
+       } else {
+               /* If the oob mode is OOB_NOT_CONNECTED, the port is
+                * disconnected due to race with PHY down. We cannot
+                * continue to discover this port
+                */
+               sas_put_device(dev);
+               pr_warn("Port %016llx is disconnected when discovering\n",
+                       SAS_ADDR(port->attached_sas_addr));
+               return -ENODEV;
        }
 
        sas_init_dev(dev);
index d4e1b12..0ea03ae 100644 (file)
@@ -4489,12 +4489,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
        phba->mbox_ext_buf_ctx.seqNum++;
        nemb_tp = phba->mbox_ext_buf_ctx.nembType;
 
-       dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
-       if (!dd_data) {
-               rc = -ENOMEM;
-               goto job_error;
-       }
-
        pbuf = (uint8_t *)dmabuf->virt;
        size = job->request_payload.payload_len;
        sg_copy_to_buffer(job->request_payload.sg_list,
@@ -4531,6 +4525,13 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
                                "2968 SLI_CONFIG ext-buffer wr all %d "
                                "ebuffers received\n",
                                phba->mbox_ext_buf_ctx.numBuf);
+
+               dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
+               if (!dd_data) {
+                       rc = -ENOMEM;
+                       goto job_error;
+               }
+
                /* mailbox command structure for base driver */
                pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
                if (!pmboxq) {
@@ -4579,6 +4580,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
        return SLI_CONFIG_HANDLED;
 
 job_error:
+       if (pmboxq)
+               mempool_free(pmboxq, phba->mbox_mem_pool);
        lpfc_bsg_dma_page_free(phba, dmabuf);
        kfree(dd_data);
 
index db4a04a..f6c8963 100644 (file)
@@ -1985,6 +1985,8 @@ out_unlock:
 
 /* Declare and initialization an instance of the FC NVME template. */
 static struct nvme_fc_port_template lpfc_nvme_template = {
+       .module = THIS_MODULE,
+
        /* initiator-based functions */
        .localport_delete  = lpfc_nvme_localport_delete,
        .remoteport_delete = lpfc_nvme_remoteport_delete,
index ae97e2f..d7e7043 100644 (file)
@@ -178,6 +178,7 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
 
        faddr = ha->flt_region_nvram;
        if (IS_QLA28XX(ha)) {
+               qla28xx_get_aux_images(vha, &active_regions);
                if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
                        faddr = ha->flt_region_nvram_sec;
        }
index 99f0a1a..cbaf178 100644 (file)
@@ -2399,7 +2399,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
        struct qla_active_regions regions = { };
        struct active_regions active_regions = { };
 
-       qla28xx_get_aux_images(vha, &active_regions);
+       qla27xx_get_active_image(vha, &active_regions);
        regions.global_image = active_regions.global;
 
        if (IS_QLA28XX(ha)) {
index 460f443..2edd9f7 100644 (file)
@@ -2401,6 +2401,7 @@ typedef struct fc_port {
        unsigned int id_changed:1;
        unsigned int scan_needed:1;
        unsigned int n2n_flag:1;
+       unsigned int explicit_logout:1;
 
        struct completion nvme_del_done;
        uint32_t nvme_prli_service_param;
index 59f6903..9dc09c1 100644 (file)
@@ -1523,6 +1523,10 @@ struct qla_flt_header {
 #define FLT_REG_NVRAM_SEC_28XX_1       0x10F
 #define FLT_REG_NVRAM_SEC_28XX_2       0x111
 #define FLT_REG_NVRAM_SEC_28XX_3       0x113
+#define FLT_REG_MPI_PRI_28XX           0xD3
+#define FLT_REG_MPI_SEC_28XX           0xF0
+#define FLT_REG_PEP_PRI_28XX           0xD1
+#define FLT_REG_PEP_SEC_28XX           0xF1
 
 struct qla_flt_region {
        uint16_t code;
index 6c28f38..aa52041 100644 (file)
@@ -533,6 +533,7 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 
        e->u.fcport.fcport = fcport;
        fcport->flags |= FCF_ASYNC_ACTIVE;
+       fcport->disc_state = DSC_LOGIN_PEND;
        return qla2x00_post_work(vha, e);
 }
 
@@ -1526,8 +1527,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
                }
        }
 
-       /* for pure Target Mode. Login will not be initiated */
-       if (vha->host->active_mode == MODE_TARGET)
+       /* Target won't initiate port login if fabric is present */
+       if (vha->host->active_mode == MODE_TARGET && !N2N_TOPO(vha->hw))
                return 0;
 
        if (fcport->flags & FCF_ASYNC_SENT) {
@@ -1719,6 +1720,10 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
                                      struct event_arg *ea)
 {
+       /* for pure Target Mode, PRLI will not be initiated */
+       if (vha->host->active_mode == MODE_TARGET)
+               return;
+
        ql_dbg(ql_dbg_disc, vha, 0x2118,
            "%s %d %8phC post PRLI\n",
            __func__, __LINE__, ea->fcport->port_name);
@@ -4852,6 +4857,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
        }
 
        INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
+       INIT_WORK(&fcport->free_work, qlt_free_session_done);
        INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
        INIT_LIST_HEAD(&fcport->gnl_entry);
        INIT_LIST_HEAD(&fcport->list);
@@ -4930,14 +4936,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
                set_bit(RSCN_UPDATE, &flags);
                clear_bit(LOCAL_LOOP_UPDATE, &flags);
 
-       } else if (ha->current_topology == ISP_CFG_N) {
-               clear_bit(RSCN_UPDATE, &flags);
-               if (qla_tgt_mode_enabled(vha)) {
-                       /* allow the other side to start the login */
-                       clear_bit(LOCAL_LOOP_UPDATE, &flags);
-                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-               }
-       } else if (ha->current_topology == ISP_CFG_NL) {
+       } else if (ha->current_topology == ISP_CFG_NL ||
+                  ha->current_topology == ISP_CFG_N) {
                clear_bit(RSCN_UPDATE, &flags);
                set_bit(LOCAL_LOOP_UPDATE, &flags);
        } else if (!vha->flags.online ||
@@ -5054,7 +5054,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                                memcpy(&ha->plogi_els_payld.data,
                                    (void *)ha->init_cb,
                                    sizeof(ha->plogi_els_payld.data));
-                               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                        } else {
                                ql_dbg(ql_dbg_init, vha, 0x00d1,
                                    "PLOGI ELS param read fail.\n");
index b25f87f..8b050f0 100644 (file)
@@ -2405,11 +2405,19 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
 static void
 qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 {
+       u16 control_flags = LCF_COMMAND_LOGO;
        logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
-       logio->control_flags =
-           cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
-       if (!sp->fcport->keep_nport_handle)
-               logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
+
+       if (sp->fcport->explicit_logout) {
+               control_flags |= LCF_EXPL_LOGO|LCF_FREE_NPORT;
+       } else {
+               control_flags |= LCF_IMPL_LOGO;
+
+               if (!sp->fcport->keep_nport_handle)
+                       control_flags |= LCF_FREE_NPORT;
+       }
+
+       logio->control_flags = cpu_to_le16(control_flags);
        logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
        logio->port_id[0] = sp->fcport->d_id.b.al_pa;
        logio->port_id[1] = sp->fcport->d_id.b.area;
@@ -2617,6 +2625,10 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        memcpy(elsio->u.els_logo.els_logo_pyld, &logo_pyld,
            sizeof(struct els_logo_payload));
+       ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3075, "LOGO buffer:");
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x010a,
+                      elsio->u.els_logo.els_logo_pyld,
+                      sizeof(*elsio->u.els_logo.els_logo_pyld));
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
@@ -2676,7 +2688,8 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
                ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
                    "PLOGI ELS IOCB:\n");
                ql_dump_buffer(ql_log_info, vha, 0x0109,
-                   (uint8_t *)els_iocb, 0x70);
+                   (uint8_t *)els_iocb,
+                   sizeof(*els_iocb));
        } else {
                els_iocb->control_flags = 1 << 13;
                els_iocb->tx_byte_count =
@@ -2688,6 +2701,11 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
                els_iocb->rx_byte_count = 0;
                els_iocb->rx_address = 0;
                els_iocb->rx_len = 0;
+               ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3076,
+                      "LOGO ELS IOCB:");
+               ql_dump_buffer(ql_log_info, vha, 0x010b,
+                              els_iocb,
+                              sizeof(*els_iocb));
        }
 
        sp->vha->qla_stats.control_requests++;
@@ -2934,7 +2952,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109,
-           (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
+           (uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
+           sizeof(*elsio->u.els_plogi.els_plogi_pyld));
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
index 2601d76..7b8a6bf 100644 (file)
@@ -1061,8 +1061,6 @@ global_port_update:
                        ql_dbg(ql_dbg_async, vha, 0x5011,
                            "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
                            mb[1], mb[2], mb[3]);
-
-                       qlt_async_event(mb[0], vha, mb);
                        break;
                }
 
@@ -1079,8 +1077,6 @@ global_port_update:
                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                set_bit(VP_CONFIG_OK, &vha->vp_flags);
-
-               qlt_async_event(mb[0], vha, mb);
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
index 0cf94f0..b7c1108 100644 (file)
@@ -3921,6 +3921,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                        vha->d_id.b24 = 0;
                                        vha->d_id.b.al_pa = 1;
                                        ha->flags.n2n_bigger = 1;
+                                       ha->flags.n2n_ae = 0;
 
                                        id.b.al_pa = 2;
                                        ql_dbg(ql_dbg_async, vha, 0x5075,
@@ -3931,6 +3932,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                            "Format 1: Remote login - Waiting for WWPN %8phC.\n",
                                            rptid_entry->u.f1.port_name);
                                        ha->flags.n2n_bigger = 0;
+                                       ha->flags.n2n_ae = 1;
                                }
                                qla24xx_post_newsess_work(vha, &id,
                                    rptid_entry->u.f1.port_name,
@@ -3942,7 +3944,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                        /* if our portname is higher then initiate N2N login */
 
                        set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
-                       ha->flags.n2n_ae = 1;
                        return;
                        break;
                case TOPO_FL:
index 941aa53..bfcd02f 100644 (file)
@@ -610,6 +610,7 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport)
 }
 
 static struct nvme_fc_port_template qla_nvme_fc_transport = {
+       .module = THIS_MODULE,
        .localport_delete = qla_nvme_localport_delete,
        .remoteport_delete = qla_nvme_remoteport_delete,
        .create_queue   = qla_nvme_alloc_queue,
index f2d5115..bbe9035 100644 (file)
@@ -847,15 +847,15 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
                                ha->flt_region_img_status_pri = start;
                        break;
                case FLT_REG_IMG_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_img_status_sec = start;
                        break;
                case FLT_REG_FW_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_fw_sec = start;
                        break;
                case FLT_REG_BOOTLOAD_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_boot_sec = start;
                        break;
                case FLT_REG_AUX_IMG_PRI_28XX:
@@ -2725,8 +2725,11 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
                    "Region %x is secure\n", region.code);
 
-               if (region.code == FLT_REG_FW ||
-                   region.code == FLT_REG_FW_SEC_27XX) {
+               switch (region.code) {
+               case FLT_REG_FW:
+               case FLT_REG_FW_SEC_27XX:
+               case FLT_REG_MPI_PRI_28XX:
+               case FLT_REG_MPI_SEC_28XX:
                        fw_array = dwptr;
 
                        /* 1st fw array */
@@ -2757,9 +2760,23 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                                buf_size_without_sfub += risc_size;
                                fw_array += risc_size;
                        }
-               } else {
-                       ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
-                           "Secure region %x not supported\n",
+                       break;
+
+               case FLT_REG_PEP_PRI_28XX:
+               case FLT_REG_PEP_SEC_28XX:
+                       fw_array = dwptr;
+
+                       /* 1st fw array */
+                       risc_size = be32_to_cpu(fw_array[3]);
+                       risc_attr = be32_to_cpu(fw_array[9]);
+
+                       buf_size_without_sfub = risc_size;
+                       fw_array += risc_size;
+                       break;
+
+               default:
+                       ql_log(ql_log_warn + ql_dbg_verbose, vha,
+                           0xffff, "Secure region %x not supported\n",
                            region.code);
                        rval = QLA_COMMAND_ERROR;
                        goto done;
@@ -2880,7 +2897,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                            "Sending Secure Flash MB Cmd\n");
                        rval = qla28xx_secure_flash_update(vha, 0, region.code,
                                buf_size_without_sfub, sfub_dma,
-                               sizeof(struct secure_flash_update_block));
+                               sizeof(struct secure_flash_update_block) >> 2);
                        if (rval != QLA_SUCCESS) {
                                ql_log(ql_log_warn, vha, 0xffff,
                                    "Secure Flash MB Cmd failed %x.", rval);
index 51b275a..68c1414 100644 (file)
@@ -1104,6 +1104,7 @@ void qlt_free_session_done(struct work_struct *work)
                }
        }
 
+       sess->explicit_logout = 0;
        spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
        sess->free_pending = 0;
 
@@ -1160,7 +1161,6 @@ void qlt_unreg_sess(struct fc_port *sess)
        sess->last_rscn_gen = sess->rscn_gen;
        sess->last_login_gen = sess->login_gen;
 
-       INIT_WORK(&sess->free_work, qlt_free_session_done);
        queue_work(sess->vha->hw->wq, &sess->free_work);
 }
 EXPORT_SYMBOL(qlt_unreg_sess);
@@ -1265,7 +1265,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
            "Scheduling sess %p for deletion %8phC\n",
            sess, sess->port_name);
 
-       INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
        WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
 }
 
@@ -4804,6 +4803,7 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
 
        switch (sess->disc_state) {
        case DSC_DELETED:
+       case DSC_LOGIN_PEND:
                qlt_plogi_ack_unref(vha, pla);
                break;
 
index 042a243..abe7f79 100644 (file)
@@ -246,6 +246,8 @@ static void tcm_qla2xxx_complete_mcmd(struct work_struct *work)
  */
 static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
 {
+       if (!mcmd)
+               return;
        INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd);
        queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work);
 }
@@ -348,6 +350,7 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
        target_sess_cmd_list_set_waiting(se_sess);
        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
+       sess->explicit_logout = 1;
        tcm_qla2xxx_put_sess(sess);
 }
 
index 8c674ec..2323432 100644 (file)
@@ -4275,7 +4275,6 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
        return QLA_SUCCESS;
 
 mem_alloc_error_exit:
-       qla4xxx_mem_free(ha);
        return QLA_ERROR;
 }
 
index 417b868..ed8d970 100644 (file)
@@ -24,6 +24,8 @@
 
 #define ISCSI_TRANSPORT_VERSION "2.0-870"
 
+#define ISCSI_SEND_MAX_ALLOWED  10
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/iscsi.h>
 
@@ -3682,6 +3684,7 @@ iscsi_if_rx(struct sk_buff *skb)
                struct nlmsghdr *nlh;
                struct iscsi_uevent *ev;
                uint32_t group;
+               int retries = ISCSI_SEND_MAX_ALLOWED;
 
                nlh = nlmsg_hdr(skb);
                if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
@@ -3712,6 +3715,10 @@ iscsi_if_rx(struct sk_buff *skb)
                                break;
                        err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
                                                  ev, sizeof(*ev));
+                       if (err == -EAGAIN && --retries < 0) {
+                               printk(KERN_WARNING "Send reply failed, error %d\n", err);
+                               break;
+                       }
                } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
                skb_pull(skb, rlen);
        }
index 7b7ef3a..412ac56 100644 (file)
@@ -8689,11 +8689,11 @@ static void __attribute__((unused)) verify_structures(void)
        BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
                data.delete_operational_queue.queue_id) != 12);
        BUILD_BUG_ON(sizeof(struct pqi_general_admin_request) != 64);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.create_operational_iq) != 64 - 11);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.create_operational_oq) != 64 - 11);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.delete_operational_queue) != 64 - 11);
 
        BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
index b2af04c..6feeb0f 100644 (file)
@@ -99,6 +99,12 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba,
         */
        ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
 
+       /*
+        * Disabling Autohibern8 feature in cadence UFS
+        * to mask unexpected interrupt trigger.
+        */
+       hba->ahit = 0;
+
        return 0;
 }
 
index baeecee..53dd876 100644 (file)
@@ -203,7 +203,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
        bsg_dev->parent = get_device(parent);
        bsg_dev->release = ufs_bsg_node_release;
 
-       dev_set_name(bsg_dev, "ufs-bsg");
+       dev_set_name(bsg_dev, "ufs-bsg%u", shost->host_no);
 
        ret = device_add(bsg_dev);
        if (ret)
index c36587b..82a0ee0 100644 (file)
@@ -168,16 +168,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
 /**
  * cdns_spi_chipselect - Select or deselect the chip select line
  * @spi:       Pointer to the spi_device structure
- * @enable:    Select (1) or deselect (0) the chip select line
+ * @is_high:   Select(0) or deselect (1) the chip select line
  */
-static void cdns_spi_chipselect(struct spi_device *spi, bool enable)
+static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
 {
        struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
        u32 ctrl_reg;
 
        ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
 
-       if (!enable) {
+       if (is_high) {
                /* Deselect the slave */
                ctrl_reg |= CDNS_SPI_CR_SSCTRL;
        } else {
index d12e149..fd6b9ca 100644 (file)
@@ -82,6 +82,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
 
 error:
        clk_disable_unprepare(p->clk);
+       pci_release_regions(pdev);
        spi_master_put(master);
        return ret;
 }
@@ -96,6 +97,7 @@ static void thunderx_spi_remove(struct pci_dev *pdev)
                return;
 
        clk_disable_unprepare(p->clk);
+       pci_release_regions(pdev);
        /* Put everything in a known state. */
        writeq(0, p->register_base + OCTEON_SPI_CFG(p));
 }
index a92aa5c..76d6b94 100644 (file)
@@ -129,10 +129,11 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
        struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
        struct chip_data *chip = spi_get_ctldata(spi);
 
+       /* Chip select logic is inverted from spi_set_cs() */
        if (chip && chip->cs_control)
-               chip->cs_control(enable);
+               chip->cs_control(!enable);
 
-       if (enable)
+       if (!enable)
                dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
        else if (dws->cs_override)
                dw_writel(dws, DW_SPI_SER, 0);
index 114801a..fb4159a 100644 (file)
@@ -611,6 +611,7 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
        master->setup = fsl_spi_setup;
        master->cleanup = fsl_spi_cleanup;
        master->transfer_one_message = fsl_spi_do_one_msg;
+       master->use_gpio_descriptors = true;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
        mpc8xxx_spi->max_bits_per_word = 32;
@@ -727,17 +728,27 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
                        }
                }
 #endif
-
-               pdata->cs_control = fsl_spi_cs_control;
+               /*
+                * Handle the case where we have one hardwired (always selected)
+                * device on the first "chipselect". Else we let the core code
+                * handle any GPIOs or native chip selects and assign the
+                * appropriate callback for dealing with the CS lines. This isn't
+                * supported on the GRLIB variant.
+                */
+               ret = gpiod_count(dev, "cs");
+               if (ret <= 0)
+                       pdata->max_chipselect = 1;
+               else
+                       pdata->cs_control = fsl_spi_cs_control;
        }
 
        ret = of_address_to_resource(np, 0, &mem);
        if (ret)
                goto err;
 
-       irq = irq_of_parse_and_map(np, 0);
-       if (!irq) {
-               ret = -EINVAL;
+       irq = platform_get_irq(ofdev, 0);
+       if (irq < 0) {
+               ret = irq;
                goto err;
        }
 
@@ -750,7 +761,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
        return 0;
 
 err:
-       irq_dispose_mapping(irq);
        return ret;
 }
 
index c36bb1b..8c5084a 100644 (file)
@@ -439,7 +439,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem,
            op->data.nbytes > f->devtype_data->txfifo)
                return false;
 
-       return true;
+       return spi_mem_default_supports_op(mem, op);
 }
 
 /* Instead of busy looping invoke readl_poll_timeout functionality. */
index 16b6b2a..9071333 100644 (file)
@@ -1443,6 +1443,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        { PCI_VDEVICE(INTEL, 0x4b2a), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x4b2b), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x4b37), LPSS_BXT_SSP },
+       /* JSL */
+       { PCI_VDEVICE(INTEL, 0x4daa), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x4dab), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x4dfb), LPSS_CNL_SSP },
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
index 2ee1feb..6678f1c 100644 (file)
@@ -678,7 +678,7 @@ static int sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t)
        if (d->unit != SPI_DELAY_UNIT_SCK)
                return -EINVAL;
 
-       val = readl_relaxed(ss->base + SPRD_SPI_CTL7);
+       val = readl_relaxed(ss->base + SPRD_SPI_CTL0);
        val &= ~(SPRD_SPI_SCK_REV | SPRD_SPI_NG_TX | SPRD_SPI_NG_RX);
        /* Set default chip selection, clock phase and clock polarity */
        val |= ss->hw_mode & SPI_CPHA ? SPRD_SPI_NG_RX : SPRD_SPI_NG_TX;
index 3cb6537..66dcb61 100644 (file)
@@ -62,6 +62,7 @@ struct ti_qspi {
        u32 dc;
 
        bool mmap_enabled;
+       int current_cs;
 };
 
 #define QSPI_PID                       (0x0)
@@ -487,6 +488,7 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi)
                                   MEM_CS_EN(spi->chip_select));
        }
        qspi->mmap_enabled = true;
+       qspi->current_cs = spi->chip_select;
 }
 
 static void ti_qspi_disable_memory_map(struct spi_device *spi)
@@ -498,6 +500,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi)
                regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
                                   MEM_CS_MASK, 0);
        qspi->mmap_enabled = false;
+       qspi->current_cs = -1;
 }
 
 static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode,
@@ -543,7 +546,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem,
 
        mutex_lock(&qspi->list_lock);
 
-       if (!qspi->mmap_enabled)
+       if (!qspi->mmap_enabled || qspi->current_cs != mem->spi->chip_select)
                ti_qspi_enable_memory_map(mem->spi);
        ti_qspi_setup_mmap_read(mem->spi, op->cmd.opcode, op->data.buswidth,
                                op->addr.nbytes, op->dummy.nbytes);
@@ -799,6 +802,7 @@ no_dma:
                }
        }
        qspi->mmap_enabled = false;
+       qspi->current_cs = -1;
 
        ret = devm_spi_register_master(&pdev->dev, master);
        if (!ret)
index 3fffe4d..f180a8e 100644 (file)
@@ -4,7 +4,7 @@
 #
 config XIL_AXIS_FIFO
        tristate "Xilinx AXI-Stream FIFO IP core driver"
-       depends on OF
+       depends on OF && HAS_IOMEM
        help
          This adds support for the Xilinx AXI-Stream FIFO IP core driver.
          The AXI Streaming FIFO allows memory mapped access to a AXI Streaming
index 4bdf44d..dc62db1 100644 (file)
@@ -623,6 +623,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
                    dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE,
                                       &devpriv->dio_buffer_phys_addr[i],
                                       GFP_KERNEL);
+               if (!devpriv->dio_buffer[i]) {
+                       dev_warn(dev->class_dev,
+                                "failed to allocate DMA buffer\n");
+                       return -ENOMEM;
+               }
        }
        /* allocate dma descriptors */
        devpriv->dma_desc = dma_alloc_coherent(&pcidev->dev,
@@ -630,6 +635,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
                                               NUM_DMA_DESCRIPTORS,
                                               &devpriv->dma_desc_phys_addr,
                                               GFP_KERNEL);
+       if (!devpriv->dma_desc) {
+               dev_warn(dev->class_dev,
+                        "failed to allocate DMA descriptors\n");
+               return -ENOMEM;
+       }
        if (devpriv->dma_desc_phys_addr & 0xf) {
                dev_warn(dev->class_dev,
                         " dma descriptors not quad-word aligned (bug)\n");
index 2aac1e0..51c665a 100644 (file)
@@ -805,8 +805,8 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
 s32 create_file(struct inode *inode, struct chain_t *p_dir,
                struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid);
 void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry);
-s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
-               struct uni_name_t *p_uniname, struct file_id_t *fid);
+s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
+                     struct uni_name_t *p_uniname, struct file_id_t *fid);
 s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
              struct chain_t *p_newdir, struct uni_name_t *p_uniname,
              struct file_id_t *fid);
index d2d3447..794000e 100644 (file)
@@ -192,8 +192,6 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
 
        exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
 
-       return sector_write(sb, sector, p_fs->vol_amap[i], 0);
-
 #ifdef CONFIG_EXFAT_DISCARD
        if (opts->discard) {
                ret = sb_issue_discard(sb, START_SECTOR(clu),
@@ -202,9 +200,13 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
                if (ret == -EOPNOTSUPP) {
                        pr_warn("discard not supported by device, disabling");
                        opts->discard = 0;
+               } else {
+                       return ret;
                }
        }
 #endif /* CONFIG_EXFAT_DISCARD */
+
+       return sector_write(sb, sector, p_fs->vol_amap[i], 0);
 }
 
 static u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
@@ -2322,8 +2324,8 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
        fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
 }
 
-s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
-               struct uni_name_t *p_uniname, struct file_id_t *fid)
+s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+                     struct uni_name_t *p_uniname, struct file_id_t *fid)
 {
        s32 ret, newentry = -1, num_old_entries, num_new_entries;
        sector_t sector_old, sector_new;
index 6e48190..9f91853 100644 (file)
@@ -1262,8 +1262,8 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
        fs_set_vol_flags(sb, VOL_DIRTY);
 
        if (olddir.dir == newdir.dir)
-               ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name,
-                                 fid);
+               ret = exfat_rename_file(new_parent_inode, &olddir, dentry,
+                                       &uni_name, fid);
        else
                ret = move_file(new_parent_inode, &olddir, dentry, &newdir,
                                &uni_name, fid);
index e763205..f61e373 100644 (file)
@@ -63,11 +63,17 @@ static int init_display(struct fbtft_par *par)
 {
        int ret;
 
-       /* Set CS active high */
-       par->spi->mode |= SPI_CS_HIGH;
+       /*
+        * Set CS active inverse polarity: just setting SPI_CS_HIGH does not
+        * work with GPIO based chip selects that are logically active high
+        * but inverted inside the GPIO library, so enforce inverted
+        * semantics.
+        */
+       par->spi->mode ^= SPI_CS_HIGH;
        ret = spi_setup(par->spi);
        if (ret) {
-               dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+               dev_err(par->info->device,
+                       "Could not set inverse CS polarity\n");
                return ret;
        }
 
index 27cc8ea..76b25df 100644 (file)
@@ -150,10 +150,17 @@ static int init_display(struct fbtft_par *par)
 
        /* enable SPI interface by having CS and MOSI low during reset */
        save_mode = par->spi->mode;
-       par->spi->mode |= SPI_CS_HIGH;
-       ret = spi_setup(par->spi); /* set CS inactive low */
+       /*
+        * Set CS active inverse polarity: just setting SPI_CS_HIGH does not
+        * work with GPIO based chip selects that are logically active high
+        * but inverted inside the GPIO library, so enforce inverted
+        * semantics.
+        */
+       par->spi->mode ^= SPI_CS_HIGH;
+       ret = spi_setup(par->spi);
        if (ret) {
-               dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+               dev_err(par->info->device,
+                       "Could not set inverse CS polarity\n");
                return ret;
        }
        write_reg(par, 0x00); /* make sure mode is set */
index ffb8498..d3e098b 100644 (file)
@@ -913,7 +913,7 @@ static int fbtft_init_display_from_property(struct fbtft_par *par)
        if (count == 0)
                return -EINVAL;
 
-       values = kmalloc_array(count, sizeof(*values), GFP_KERNEL);
+       values = kmalloc_array(count + 1, sizeof(*values), GFP_KERNEL);
        if (!values)
                return -ENOMEM;
 
@@ -926,9 +926,9 @@ static int fbtft_init_display_from_property(struct fbtft_par *par)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        index = -1;
-       while (index < count) {
-               val = values[++index];
+       val = values[++index];
 
+       while (index < count) {
                if (val & FBTFT_OF_INIT_CMD) {
                        val &= 0xFFFF;
                        i = 0;
index fb395cf..f20ab21 100644 (file)
@@ -6,6 +6,7 @@
 config NET_VENDOR_HP
        bool "HP devices"
        default y
+       depends on ETHERNET
        depends on ISA || EISA || PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
index 1b9b436..a20c0bf 100644 (file)
@@ -571,8 +571,7 @@ static int gigaset_initcshw(struct cardstate *cs)
 {
        struct usb_cardstate *ucs;
 
-       cs->hw.usb = ucs =
-               kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
+       cs->hw.usb = ucs = kzalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
        if (!ucs) {
                pr_err("out of memory\n");
                return -ENOMEM;
@@ -584,9 +583,6 @@ static int gigaset_initcshw(struct cardstate *cs)
        ucs->bchars[3] = 0;
        ucs->bchars[4] = 0x11;
        ucs->bchars[5] = 0x13;
-       ucs->bulk_out_buffer = NULL;
-       ucs->bulk_out_urb = NULL;
-       ucs->read_urb = NULL;
        tasklet_init(&cs->write_tasklet,
                     gigaset_modem_fill, (unsigned long) cs);
 
@@ -685,6 +681,11 @@ static int gigaset_probe(struct usb_interface *interface,
                return -ENODEV;
        }
 
+       if (hostif->desc.bNumEndpoints < 2) {
+               dev_err(&interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
        dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
        /* allocate memory for our device state and initialize it */
@@ -704,6 +705,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
        endpoint = &hostif->endpoint[0].desc;
 
+       if (!usb_endpoint_is_bulk_out(endpoint)) {
+               dev_err(&interface->dev, "missing bulk-out endpoint\n");
+               retval = -ENODEV;
+               goto error;
+       }
+
        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
        ucs->bulk_out_size = buffer_size;
        ucs->bulk_out_epnum = usb_endpoint_num(endpoint);
@@ -723,6 +730,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
        endpoint = &hostif->endpoint[1].desc;
 
+       if (!usb_endpoint_is_int_in(endpoint)) {
+               dev_err(&interface->dev, "missing int-in endpoint\n");
+               retval = -ENODEV;
+               goto error;
+       }
+
        ucs->busy = 0;
 
        ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
index 5319909..e7f4ddc 100644 (file)
@@ -3,6 +3,7 @@ config OCTEON_ETHERNET
        tristate "Cavium Networks Octeon Ethernet support"
        depends on CAVIUM_OCTEON_SOC || COMPILE_TEST
        depends on NETDEVICES
+       depends on BROKEN
        select PHYLIB
        select MDIO_OCTEON
        help
index a6886cc..56d116d 100644 (file)
@@ -41,7 +41,7 @@ struct ql_stats {
        int stat_offset;
 };
 
-#define QL_SIZEOF(m) FIELD_SIZEOF(struct ql_adapter, m)
+#define QL_SIZEOF(m) sizeof_field(struct ql_adapter, m)
 #define QL_OFF(m) offsetof(struct ql_adapter, m)
 
 static const struct ql_stats ql_gstrings_stats[] = {
index 4fac9dc..a7cac07 100644 (file)
@@ -70,7 +70,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
        phost_conf = pusbd->actconfig;
        pconf_desc = &phost_conf->desc;
 
-       phost_iface = &usb_intf->altsetting[0];
+       phost_iface = usb_intf->cur_altsetting;
        piface_desc = &phost_iface->desc;
 
        pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
index ba12882..a87562f 100644 (file)
@@ -247,7 +247,7 @@ static uint r8712_usb_dvobj_init(struct _adapter *padapter)
 
        pdvobjpriv->padapter = padapter;
        padapter->eeprom_address_size = 6;
-       phost_iface = &pintf->altsetting[0];
+       phost_iface = pintf->cur_altsetting;
        piface_desc = &phost_iface->desc;
        pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
        if (pusbd->speed == USB_SPEED_HIGH) {
index 02148a2..4458c1e 100644 (file)
@@ -3309,7 +3309,7 @@ static int __init vchiq_driver_init(void)
        return 0;
 
 region_unregister:
-       platform_driver_unregister(&vchiq_driver);
+       unregister_chrdev_region(vchiq_devid, 1);
 
 class_destroy:
        class_destroy(vchiq_class);
index b722e97..b13d734 100644 (file)
@@ -16,7 +16,7 @@
 #include "traces.h"
 #include "hif_tx_mib.h"
 
-#define WFX_INVALID_RATE_ID (0xFF)
+#define WFX_INVALID_RATE_ID    15
 #define WFX_LINK_ID_NO_ASSOC   15
 #define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
 
@@ -184,7 +184,7 @@ static int wfx_tx_policy_get(struct wfx_vif *wvif,
                 */
                entry = list_entry(cache->free.prev, struct tx_policy, link);
                memcpy(entry->rates, wanted.rates, sizeof(entry->rates));
-               entry->uploaded = 0;
+               entry->uploaded = false;
                entry->usage_count = 0;
                idx = entry - cache->cache;
        }
@@ -202,6 +202,8 @@ static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx)
        int usage, locked;
        struct tx_policy_cache *cache = &wvif->tx_policy_cache;
 
+       if (idx == WFX_INVALID_RATE_ID)
+               return;
        spin_lock_bh(&cache->lock);
        locked = list_empty(&cache->free);
        usage = wfx_tx_policy_release(cache, &cache->cache[idx]);
@@ -239,7 +241,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif)
                        dst->terminate = 1;
                        dst->count_init = 1;
                        memcpy(&dst->rates, src->rates, sizeof(src->rates));
-                       src->uploaded = 1;
+                       src->uploaded = true;
                        arg->num_tx_rate_policies++;
                }
        }
@@ -249,7 +251,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif)
        return 0;
 }
 
-static void wfx_tx_policy_upload_work(struct work_struct *work)
+void wfx_tx_policy_upload_work(struct work_struct *work)
 {
        struct wfx_vif *wvif =
                container_of(work, struct wfx_vif, tx_policy_upload_work);
@@ -270,7 +272,6 @@ void wfx_tx_policy_init(struct wfx_vif *wvif)
        spin_lock_init(&cache->lock);
        INIT_LIST_HEAD(&cache->used);
        INIT_LIST_HEAD(&cache->free);
-       INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
 
        for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i)
                list_add(&cache->cache[i].link, &cache->free);
@@ -523,9 +524,9 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
                for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) {
                        if (rates[i + 1].idx == rates[i].idx &&
                            rates[i].idx != -1) {
-                               rates[i].count =
-                                       max_t(int, rates[i].count,
-                                             rates[i + 1].count);
+                               rates[i].count += rates[i + 1].count;
+                               if (rates[i].count > 15)
+                                       rates[i].count = 15;
                                rates[i + 1].idx = -1;
                                rates[i + 1].count = 0;
 
@@ -537,6 +538,17 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
                        }
                }
        } while (!finished);
+       // Ensure that MCS0 or 1Mbps is present at the end of the retry list
+       for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+               if (rates[i].idx == 0)
+                       break;
+               if (rates[i].idx == -1) {
+                       rates[i].idx = 0;
+                       rates[i].count = 8; // == hw->max_rate_tries
+                       rates[i].flags = rates[i - 1].flags & IEEE80211_TX_RC_MCS;
+                       break;
+               }
+       }
        // All retries use long GI
        for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
                rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
@@ -550,7 +562,8 @@ static u8 wfx_tx_get_rate_id(struct wfx_vif *wvif,
 
        rate_id = wfx_tx_policy_get(wvif,
                                    tx_info->driver_rates, &tx_policy_renew);
-       WARN(rate_id == WFX_INVALID_RATE_ID, "unable to get a valid Tx policy");
+       if (rate_id == WFX_INVALID_RATE_ID)
+               dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy");
 
        if (tx_policy_renew) {
                /* FIXME: It's not so optimal to stop TX queues every now and
@@ -679,7 +692,7 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
        struct ieee80211_sta *sta = control ? control->sta : NULL;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       size_t driver_data_room = FIELD_SIZEOF(struct ieee80211_tx_info,
+       size_t driver_data_room = sizeof_field(struct ieee80211_tx_info,
                                               rate_driver_data);
 
        compiletime_assert(sizeof(struct wfx_tx_priv) <= driver_data_room,
@@ -735,7 +748,9 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg)
                rate = &tx_info->status.rates[i];
                if (rate->idx < 0)
                        break;
-               if (tx_count < rate->count && arg->status && arg->ack_failures)
+               if (tx_count < rate->count &&
+                   arg->status == HIF_STATUS_RETRY_EXCEEDED &&
+                   arg->ack_failures)
                        dev_dbg(wvif->wdev->dev, "all retries were not consumed: %d != %d\n",
                                rate->count, tx_count);
                if (tx_count <= rate->count && tx_count &&
index 29faa56..0fc388d 100644 (file)
@@ -39,9 +39,9 @@ struct wfx_link_entry {
 
 struct tx_policy {
        struct list_head link;
+       int usage_count;
        u8 rates[12];
-       u8 usage_count;
-       u8 uploaded;
+       bool uploaded;
 };
 
 struct tx_policy_cache {
@@ -61,6 +61,7 @@ struct wfx_tx_priv {
 } __packed;
 
 void wfx_tx_policy_init(struct wfx_vif *wvif);
+void wfx_tx_policy_upload_work(struct work_struct *work);
 
 void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
            struct sk_buff *skb);
index bb091e3..9be7488 100644 (file)
@@ -147,7 +147,6 @@ static inline int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required)
        }
        if (!required)
                val.unpmf_allowed = 1;
-       cpu_to_le32s((u32 *) &val);
        return hif_write_mib(wvif->wdev, wvif->id,
                             HIF_MIB_ID_PROTECTED_MGMT_POLICY,
                             &val, sizeof(val));
index 986a2ef..3b47b6c 100644 (file)
@@ -289,7 +289,7 @@ struct wfx_dev *wfx_init_common(struct device *dev,
        hw->sta_data_size = sizeof(struct wfx_sta_priv);
        hw->queues = 4;
        hw->max_rates = 8;
-       hw->max_rate_tries = 15;
+       hw->max_rate_tries = 8;
        hw->extra_tx_headroom = sizeof(struct hif_sl_msg_hdr) +
                                sizeof(struct hif_msg)
                                + sizeof(struct hif_req_tx)
index c7ee908..680fed3 100644 (file)
@@ -422,6 +422,7 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb,
                break;
        case do_wep:
                wfx_tx_lock(wvif->wdev);
+               WARN_ON(wvif->wep_pending_skb);
                wvif->wep_default_key_id = tx_priv->hw_key->keyidx;
                wvif->wep_pending_skb = skb;
                if (!schedule_work(&wvif->wep_key_work))
index 29848a2..471dd15 100644 (file)
@@ -592,6 +592,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif)
        wfx_tx_flush(wvif->wdev);
        hif_keep_alive_period(wvif, 0);
        hif_reset(wvif, false);
+       wfx_tx_policy_init(wvif);
        hif_set_output_power(wvif, wvif->wdev->output_power * 10);
        wvif->dtim_period = 0;
        hif_set_macaddr(wvif, wvif->vif->addr);
@@ -880,8 +881,10 @@ static int wfx_update_beaconing(struct wfx_vif *wvif)
                if (wvif->state != WFX_STATE_AP ||
                    wvif->beacon_int != conf->beacon_int) {
                        wfx_tx_lock_flush(wvif->wdev);
-                       if (wvif->state != WFX_STATE_PASSIVE)
+                       if (wvif->state != WFX_STATE_PASSIVE) {
                                hif_reset(wvif, false);
+                               wfx_tx_policy_init(wvif);
+                       }
                        wvif->state = WFX_STATE_PASSIVE;
                        wfx_start_ap(wvif);
                        wfx_tx_unlock(wvif->wdev);
@@ -1567,6 +1570,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work);
        INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work);
 
+       INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
        mutex_unlock(&wdev->conf_mutex);
 
        hif_set_macaddr(wvif, vif->addr);
index ac13666..082c16a 100644 (file)
@@ -4,6 +4,7 @@ config PRISM2_USB
        depends on WLAN && USB && CFG80211
        select WIRELESS_EXT
        select WEXT_PRIV
+       select CRC32
        help
          This is the wlan-ng prism 2.5/3 USB driver for a wide range of
          old USB wireless devices.
index e877b91..30ea37e 100644 (file)
@@ -708,7 +708,7 @@ static int __init cxgbit_init(void)
        pr_info("%s dcb enabled.\n", DRV_NAME);
        register_dcbevent_notifier(&cxgbit_dcbevent_nb);
 #endif
-       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+       BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) <
                     sizeof(union cxgbit_skb_cb));
        return 0;
 }
index 59b79fc..79b2786 100644 (file)
@@ -108,7 +108,7 @@ config THERMAL_DEFAULT_GOV_USER_SPACE
 
 config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR
        bool "power_allocator"
-       select THERMAL_GOV_POWER_ALLOCATOR
+       depends on THERMAL_GOV_POWER_ALLOCATOR
        help
          Select this if you want to control temperature based on
          system and device power allocation. This governor can only
index a8dc8af..1ba9bc6 100644 (file)
@@ -2270,27 +2270,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
                mode |= ATMEL_US_USMODE_NORMAL;
        }
 
-       /* set the mode, clock divisor, parity, stop bits and data size */
-       atmel_uart_writel(port, ATMEL_US_MR, mode);
-
-       /*
-        * when switching the mode, set the RTS line state according to the
-        * new mode, otherwise keep the former state
-        */
-       if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
-               unsigned int rts_state;
-
-               if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
-                       /* let the hardware control the RTS line */
-                       rts_state = ATMEL_US_RTSDIS;
-               } else {
-                       /* force RTS line to low level */
-                       rts_state = ATMEL_US_RTSEN;
-               }
-
-               atmel_uart_writel(port, ATMEL_US_CR, rts_state);
-       }
-
        /*
         * Set the baud rate:
         * Fractional baudrate allows to setup output frequency more
@@ -2317,6 +2296,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (!(port->iso7816.flags & SER_ISO7816_ENABLED))
                atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+
+       /* set the mode, clock divisor, parity, stop bits and data size */
+       atmel_uart_writel(port, ATMEL_US_MR, mode);
+
+       /*
+        * when switching the mode, set the RTS line state according to the
+        * new mode, otherwise keep the former state
+        */
+       if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
+               unsigned int rts_state;
+
+               if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+                       /* let the hardware control the RTS line */
+                       rts_state = ATMEL_US_RTSDIS;
+               } else {
+                       /* force RTS line to low level */
+                       rts_state = ATMEL_US_RTSEN;
+               }
+
+               atmel_uart_writel(port, ATMEL_US_CR, rts_state);
+       }
+
        atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
        atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
        atmel_port->tx_stopped = false;
index 1cbae07..f6c45a7 100644 (file)
@@ -1580,6 +1580,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
        int num_newlines = 0;
        bool replaced = false;
        void __iomem *tf;
+       int locked = 1;
 
        if (is_uartdm)
                tf = port->membase + UARTDM_TF;
@@ -1592,7 +1593,13 @@ static void __msm_console_write(struct uart_port *port, const char *s,
                        num_newlines++;
        count += num_newlines;
 
-       spin_lock(&port->lock);
+       if (port->sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock(&port->lock);
+       else
+               spin_lock(&port->lock);
+
        if (is_uartdm)
                msm_reset_dm_count(port, count);
 
@@ -1628,7 +1635,9 @@ static void __msm_console_write(struct uart_port *port, const char *s,
                iowrite32_rep(tf, buf, 1);
                i += num_chars;
        }
-       spin_unlock(&port->lock);
+
+       if (locked)
+               spin_unlock(&port->lock);
 }
 
 static void msm_console_write(struct console *co, const char *s,
index b0a6eb1..7c27827 100644 (file)
@@ -2834,6 +2834,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
        if (uport->cons && uport->dev)
                of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
 
+       tty_port_link_device(port, drv->tty_driver, uport->line);
        uart_configure_port(drv, state, uport);
 
        port->console = uart_console(uport);
index 31df235..f60a59d 100644 (file)
@@ -679,6 +679,9 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
        if (ims & SPRD_IMSR_TIMEOUT)
                serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
 
+       if (ims & SPRD_IMSR_BREAK_DETECT)
+               serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
+
        if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT |
                   SPRD_IMSR_TIMEOUT))
                sprd_rx(port);
index 044c3cb..5023c85 100644 (file)
@@ -89,7 +89,8 @@ void tty_port_link_device(struct tty_port *port,
 {
        if (WARN_ON(index >= driver->num))
                return;
-       driver->ports[index] = port;
+       if (!driver->ports[index])
+               driver->ports[index] = port;
 }
 EXPORT_SYMBOL_GPL(tty_port_link_device);
 
index 8b0ea8c..635cf04 100644 (file)
@@ -2124,10 +2124,11 @@ resubmit:
 /*
  * Start the modem : init the data and start kernel thread
  */
-static int uea_boot(struct uea_softc *sc)
+static int uea_boot(struct uea_softc *sc, struct usb_interface *intf)
 {
-       int ret, size;
        struct intr_pkt *intr;
+       int ret = -ENOMEM;
+       int size;
 
        uea_enters(INS_TO_USBDEV(sc));
 
@@ -2152,6 +2153,11 @@ static int uea_boot(struct uea_softc *sc)
        if (UEA_CHIP_VERSION(sc) == ADI930)
                load_XILINX_firmware(sc);
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
        intr = kmalloc(size, GFP_KERNEL);
        if (!intr)
                goto err0;
@@ -2163,8 +2169,7 @@ static int uea_boot(struct uea_softc *sc)
        usb_fill_int_urb(sc->urb_int, sc->usb_dev,
                         usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
                         intr, size, uea_intr, sc,
-                        sc->usb_dev->actconfig->interface[0]->altsetting[0].
-                        endpoint[0].desc.bInterval);
+                        intf->cur_altsetting->endpoint[0].desc.bInterval);
 
        ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
        if (ret < 0) {
@@ -2179,6 +2184,7 @@ static int uea_boot(struct uea_softc *sc)
        sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
        if (IS_ERR(sc->kthread)) {
                uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+               ret = PTR_ERR(sc->kthread);
                goto err2;
        }
 
@@ -2193,7 +2199,7 @@ err1:
        kfree(intr);
 err0:
        uea_leaves(INS_TO_USBDEV(sc));
-       return -ENOMEM;
+       return ret;
 }
 
 /*
@@ -2548,7 +2554,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
                }
        }
 
-       ret = uea_boot(sc);
+       ret = uea_boot(sc, intf);
        if (ret < 0)
                goto error;
 
index dbea284..4e12a32 100644 (file)
@@ -1275,7 +1275,7 @@ EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);
 
 static int __init usbatm_usb_init(void)
 {
-       if (sizeof(struct usbatm_control) > FIELD_SIZEOF(struct sk_buff, cb)) {
+       if (sizeof(struct usbatm_control) > sizeof_field(struct sk_buff, cb)) {
                printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);
                return -EIO;
        }
index 87338f9..ed204cb 100644 (file)
@@ -156,7 +156,8 @@ static int usb_conn_probe(struct platform_device *pdev)
 
        info->vbus = devm_regulator_get(dev, "vbus");
        if (IS_ERR(info->vbus)) {
-               dev_err(dev, "failed to get vbus\n");
+               if (PTR_ERR(info->vbus) != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get vbus\n");
                return PTR_ERR(info->vbus);
        }
 
index 281568d..aa45840 100644 (file)
@@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
                if (hcd->self.uses_pio_for_control)
                        return ret;
-               if (hcd_uses_dma(hcd)) {
+               if (hcd->localmem_pool) {
+                       ret = hcd_alloc_coherent(
+                                       urb->dev->bus, mem_flags,
+                                       &urb->setup_dma,
+                                       (void **)&urb->setup_packet,
+                                       sizeof(struct usb_ctrlrequest),
+                                       DMA_TO_DEVICE);
+                       if (ret)
+                               return ret;
+                       urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
+               } else if (hcd_uses_dma(hcd)) {
                        if (object_is_on_stack(urb->setup_packet)) {
                                WARN_ONCE(1, "setup packet is on stack\n");
                                return -EAGAIN;
@@ -1424,23 +1434,22 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                                urb->setup_dma))
                                return -EAGAIN;
                        urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
-               } else if (hcd->localmem_pool) {
-                       ret = hcd_alloc_coherent(
-                                       urb->dev->bus, mem_flags,
-                                       &urb->setup_dma,
-                                       (void **)&urb->setup_packet,
-                                       sizeof(struct usb_ctrlrequest),
-                                       DMA_TO_DEVICE);
-                       if (ret)
-                               return ret;
-                       urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
                }
        }
 
        dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
        if (urb->transfer_buffer_length != 0
            && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-               if (hcd_uses_dma(hcd)) {
+               if (hcd->localmem_pool) {
+                       ret = hcd_alloc_coherent(
+                                       urb->dev->bus, mem_flags,
+                                       &urb->transfer_dma,
+                                       &urb->transfer_buffer,
+                                       urb->transfer_buffer_length,
+                                       dir);
+                       if (ret == 0)
+                               urb->transfer_flags |= URB_MAP_LOCAL;
+               } else if (hcd_uses_dma(hcd)) {
                        if (urb->num_sgs) {
                                int n;
 
@@ -1491,15 +1500,6 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                else
                                        urb->transfer_flags |= URB_DMA_MAP_SINGLE;
                        }
-               } else if (hcd->localmem_pool) {
-                       ret = hcd_alloc_coherent(
-                                       urb->dev->bus, mem_flags,
-                                       &urb->transfer_dma,
-                                       &urb->transfer_buffer,
-                                       urb->transfer_buffer_length,
-                                       dir);
-                       if (ret == 0)
-                               urb->transfer_flags |= URB_MAP_LOCAL;
                }
                if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
                                URB_SETUP_MAP_LOCAL)))
index 0eab79f..da923ec 100644 (file)
@@ -45,6 +45,7 @@ void usb_init_urb(struct urb *urb)
        if (urb) {
                memset(urb, 0, sizeof(*urb));
                kref_init(&urb->kref);
+               INIT_LIST_HEAD(&urb->urb_list);
                INIT_LIST_HEAD(&urb->anchor_list);
        }
 }
index 023f035..294276f 100644 (file)
@@ -29,7 +29,8 @@
 #define PCI_DEVICE_ID_INTEL_BXT_M              0x1aaa
 #define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 #define PCI_DEVICE_ID_INTEL_KBP                        0xa2b0
-#define PCI_DEVICE_ID_INTEL_CMLH               0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLLP              0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLH               0x06ee
 #define PCI_DEVICE_ID_INTEL_GLK                        0x31aa
 #define PCI_DEVICE_ID_INTEL_CNPLP              0x9dee
 #define PCI_DEVICE_ID_INTEL_CNPH               0xa36e
@@ -308,6 +309,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
          (kernel_ulong_t) &dwc3_pci_mrfld_properties, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLLP),
+         (kernel_ulong_t) &dwc3_pci_intel_properties, },
+
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
          (kernel_ulong_t) &dwc3_pci_intel_properties, },
 
index 3996b9c..fd1b100 100644 (file)
@@ -1117,6 +1117,9 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
                const struct dwc3_event_depevt *event)
 {
+       struct dwc3_ep  *dep = dwc->eps[event->endpoint_number];
+       u8              cmd;
+
        switch (event->endpoint_event) {
        case DWC3_DEPEVT_XFERCOMPLETE:
                dwc3_ep0_xfer_complete(dwc, event);
@@ -1129,7 +1132,12 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
        case DWC3_DEPEVT_XFERINPROGRESS:
        case DWC3_DEPEVT_RXTXFIFOEVT:
        case DWC3_DEPEVT_STREAMEVT:
+               break;
        case DWC3_DEPEVT_EPCMDCMPLT:
+               cmd = DEPEVT_PARAMETER_CMD(event->parameters);
+
+               if (cmd == DWC3_DEPCMD_ENDTRANSFER)
+                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
                break;
        }
 }
index a9aba71..0c960a9 100644 (file)
@@ -2491,7 +2491,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
 
        req->request.actual = req->request.length - req->remaining;
 
-       if (!dwc3_gadget_ep_request_completed(req) &&
+       if (!dwc3_gadget_ep_request_completed(req) ||
                        req->num_pending_sgs) {
                __dwc3_gadget_kick_transfer(dep);
                goto out;
@@ -2719,6 +2719,9 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
+       if (!interrupt)
+               dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+
        if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
                udelay(100);
 }
index 6ce0440..460d5d7 100644 (file)
@@ -621,8 +621,12 @@ static void ecm_disable(struct usb_function *f)
 
        DBG(cdev, "ecm deactivated\n");
 
-       if (ecm->port.in_ep->enabled)
+       if (ecm->port.in_ep->enabled) {
                gether_disconnect(&ecm->port);
+       } else {
+               ecm->port.in_ep->desc = NULL;
+               ecm->port.out_ep->desc = NULL;
+       }
 
        usb_ep_disable(ecm->notify);
        ecm->notify->desc = NULL;
index ce1d023..0bbccac 100644 (file)
@@ -3509,7 +3509,7 @@ static void ffs_free_inst(struct usb_function_instance *f)
 
 static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
 {
-       if (strlen(name) >= FIELD_SIZEOF(struct ffs_dev, name))
+       if (strlen(name) >= sizeof_field(struct ffs_dev, name))
                return -ENAMETOOLONG;
        return ffs_name_dev(to_f_fs_opts(fi)->dev, name);
 }
index d48df36..0d8e4a3 100644 (file)
@@ -618,6 +618,7 @@ static void rndis_disable(struct usb_function *f)
        gether_disconnect(&rndis->port);
 
        usb_ep_disable(rndis->notify);
+       rndis->notify->desc = NULL;
 }
 
 /*-------------------------------------------------------------------------*/
index aa2f77f..8a5c9b3 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/* PID Codes that are used here, from EHCI specification, Table 3-16. */
+#define PID_CODE_IN    1
+#define PID_CODE_SETUP 2
+
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
@@ -190,7 +194,7 @@ static int qtd_copy_status (
        int     status = -EINPROGRESS;
 
        /* count IN/OUT bytes, not SETUP (even short packets) */
-       if (likely (QTD_PID (token) != 2))
+       if (likely(QTD_PID(token) != PID_CODE_SETUP))
                urb->actual_length += length - QTD_LENGTH (token);
 
        /* don't modify error codes */
@@ -206,6 +210,13 @@ static int qtd_copy_status (
                if (token & QTD_STS_BABBLE) {
                        /* FIXME "must" disable babbling device's port too */
                        status = -EOVERFLOW;
+               /*
+                * When MMF is active and PID Code is IN, queue is halted.
+                * EHCI Specification, Table 4-13.
+                */
+               } else if ((token & QTD_STS_MMF) &&
+                                       (QTD_PID(token) == PID_CODE_IN)) {
+                       status = -EPROTO;
                /* CERR nonzero + halt --> stall */
                } else if (QTD_CERR(token)) {
                        status = -EPIPE;
index b7d23c4..7a3a29e 100644 (file)
@@ -806,7 +806,7 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
 
 static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
                                             u32 *status, u32 portsc,
-                                            unsigned long flags)
+                                            unsigned long *flags)
 {
        struct xhci_bus_state *bus_state;
        struct xhci_hcd *xhci;
@@ -860,11 +860,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
                xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                xhci_set_link_state(xhci, port, XDEV_U0);
 
-               spin_unlock_irqrestore(&xhci->lock, flags);
+               spin_unlock_irqrestore(&xhci->lock, *flags);
                time_left = wait_for_completion_timeout(
                        &bus_state->rexit_done[wIndex],
                        msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS));
-               spin_lock_irqsave(&xhci->lock, flags);
+               spin_lock_irqsave(&xhci->lock, *flags);
 
                if (time_left) {
                        slot_id = xhci_find_slot_id_by_port(hcd, xhci,
@@ -920,11 +920,13 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
 {
        struct xhci_bus_state *bus_state;
        struct xhci_hcd *xhci;
+       struct usb_hcd *hcd;
        u32 link_state;
        u32 portnum;
 
        bus_state = &port->rhub->bus_state;
        xhci = hcd_to_xhci(port->rhub->hcd);
+       hcd = port->rhub->hcd;
        link_state = portsc & PORT_PLS_MASK;
        portnum = port->hcd_portnum;
 
@@ -952,12 +954,20 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
                        bus_state->suspended_ports &= ~(1 << portnum);
        }
 
+       /* remote wake resume signaling complete */
+       if (bus_state->port_remote_wakeup & (1 << portnum) &&
+           link_state != XDEV_RESUME &&
+           link_state != XDEV_RECOVERY) {
+               bus_state->port_remote_wakeup &= ~(1 << portnum);
+               usb_hcd_end_port_resume(&hcd->self, portnum);
+       }
+
        xhci_hub_report_usb3_link_state(xhci, status, portsc);
        xhci_del_comp_mod_timer(xhci, portsc, portnum);
 }
 
 static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
-                                     u32 portsc, unsigned long flags)
+                                     u32 portsc, unsigned long *flags)
 {
        struct xhci_bus_state *bus_state;
        u32 link_state;
@@ -1007,7 +1017,7 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
 static u32 xhci_get_port_status(struct usb_hcd *hcd,
                struct xhci_bus_state *bus_state,
        u16 wIndex, u32 raw_port_status,
-               unsigned long flags)
+               unsigned long *flags)
        __releases(&xhci->lock)
        __acquires(&xhci->lock)
 {
@@ -1130,7 +1140,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                }
                trace_xhci_get_port_status(wIndex, temp);
                status = xhci_get_port_status(hcd, bus_state, wIndex, temp,
-                                             flags);
+                                             &flags);
                if (status == 0xffffffff)
                        goto error;
 
index e16eda6..3b1388f 100644 (file)
@@ -1909,13 +1909,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);
 
        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;
index a0025d2..4917c5b 100644 (file)
@@ -519,6 +519,18 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
        retval = xhci_resume(xhci, hibernated);
        return retval;
 }
+
+static void xhci_pci_shutdown(struct usb_hcd *hcd)
+{
+       struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+
+       xhci_shutdown(hcd);
+
+       /* Yet another workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(pdev, PCI_D3hot);
+}
 #endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
@@ -556,6 +568,7 @@ static int __init xhci_pci_init(void)
 #ifdef CONFIG_PM
        xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
        xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
+       xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
 #endif
        return pci_register_driver(&xhci_pci_driver);
 }
index 6475c3d..d23f740 100644 (file)
@@ -1628,7 +1628,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
                slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
                if (slot_id && xhci->devs[slot_id])
                        xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
-               bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
        }
 
        if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1648,6 +1647,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                         */
                        bus_state->port_remote_wakeup |= 1 << hcd_portnum;
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
+                       usb_hcd_start_port_resume(&hcd->self, hcd_portnum);
                        xhci_set_link_state(xhci, port, XDEV_U0);
                        /* Need to wait until the next link state change
                         * indicates the device is actually in U0.
@@ -1688,7 +1688,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
                if (slot_id && xhci->devs[slot_id])
                        xhci_ring_device(xhci, slot_id);
                if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
-                       bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                        usb_wakeup_notification(hcd->self.root_hub,
                                        hcd_portnum + 1);
@@ -2382,7 +2381,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        case COMP_SUCCESS:
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
                        break;
-               if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+               if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
+                   ep_ring->last_td_was_short)
                        trb_comp_code = COMP_SHORT_PACKET;
                else
                        xhci_warn_ratelimited(xhci,
index 6721d05..dbac0fa 100644 (file)
@@ -770,7 +770,7 @@ static void xhci_stop(struct usb_hcd *hcd)
  *
  * This will only ever be called with the main usb_hcd (the USB3 roothub).
  */
-static void xhci_shutdown(struct usb_hcd *hcd)
+void xhci_shutdown(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
@@ -789,11 +789,8 @@ static void xhci_shutdown(struct usb_hcd *hcd)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "xhci_shutdown completed - status = %x",
                        readl(&xhci->op_regs->status));
-
-       /* Yet another workaround for spurious wakeups at shutdown with HSW */
-       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
-               pci_set_power_state(to_pci_dev(hcd->self.sysdev), PCI_D3hot);
 }
+EXPORT_SYMBOL_GPL(xhci_shutdown);
 
 #ifdef CONFIG_PM
 static void xhci_save_registers(struct xhci_hcd *xhci)
@@ -973,7 +970,7 @@ static bool xhci_pending_portevent(struct xhci_hcd *xhci)
 int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 {
        int                     rc = 0;
-       unsigned int            delay = XHCI_MAX_HALT_USEC;
+       unsigned int            delay = XHCI_MAX_HALT_USEC * 2;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
        u32                     res;
index dc6f62a..13d8838 100644 (file)
@@ -2050,6 +2050,7 @@ int xhci_start(struct xhci_hcd *xhci);
 int xhci_reset(struct xhci_hcd *xhci);
 int xhci_run(struct usb_hcd *hcd);
 int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
+void xhci_shutdown(struct usb_hcd *hcd);
 void xhci_init_driver(struct hc_driver *drv,
                      const struct xhci_driver_overrides *over);
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
index 6f5edb9..d8d157c 100644 (file)
@@ -669,7 +669,7 @@ static int adu_probe(struct usb_interface *interface,
        init_waitqueue_head(&dev->read_wait);
        init_waitqueue_head(&dev->write_wait);
 
-       res = usb_find_common_endpoints_reverse(&interface->altsetting[0],
+       res = usb_find_common_endpoints_reverse(interface->cur_altsetting,
                        NULL, NULL,
                        &dev->interrupt_in_endpoint,
                        &dev->interrupt_out_endpoint);
index 4afb5dd..e9437a1 100644 (file)
@@ -322,7 +322,7 @@ static int idmouse_probe(struct usb_interface *interface,
        int result;
 
        /* check if we have gotten the data or the hid interface */
-       iface_desc = &interface->altsetting[0];
+       iface_desc = interface->cur_altsetting;
        if (iface_desc->desc.bInterfaceClass != 0x0A)
                return -ENODEV;
 
index ac2b4fc..f48a23a 100644 (file)
@@ -1039,12 +1039,18 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 
                mutex_lock(&rp->fetch_lock);
                spin_lock_irqsave(&rp->b_lock, flags);
-               mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
-               kfree(rp->b_vec);
-               rp->b_vec  = vec;
-               rp->b_size = size;
-               rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
-               rp->cnt_lost = 0;
+               if (rp->mmap_active) {
+                       mon_free_buff(vec, size/CHUNK_SIZE);
+                       kfree(vec);
+                       ret = -EBUSY;
+               } else {
+                       mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+                       kfree(rp->b_vec);
+                       rp->b_vec  = vec;
+                       rp->b_size = size;
+                       rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
+                       rp->cnt_lost = 0;
+               }
                spin_unlock_irqrestore(&rp->b_lock, flags);
                mutex_unlock(&rp->fetch_lock);
                }
@@ -1216,13 +1222,21 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 static void mon_bin_vma_open(struct vm_area_struct *vma)
 {
        struct mon_reader_bin *rp = vma->vm_private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rp->b_lock, flags);
        rp->mmap_active++;
+       spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 static void mon_bin_vma_close(struct vm_area_struct *vma)
 {
+       unsigned long flags;
+
        struct mon_reader_bin *rp = vma->vm_private_data;
+       spin_lock_irqsave(&rp->b_lock, flags);
        rp->mmap_active--;
+       spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 /*
@@ -1234,16 +1248,12 @@ static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf)
        unsigned long offset, chunk_idx;
        struct page *pageptr;
 
-       mutex_lock(&rp->fetch_lock);
        offset = vmf->pgoff << PAGE_SHIFT;
-       if (offset >= rp->b_size) {
-               mutex_unlock(&rp->fetch_lock);
+       if (offset >= rp->b_size)
                return VM_FAULT_SIGBUS;
-       }
        chunk_idx = offset / CHUNK_SIZE;
        pageptr = rp->b_vec[chunk_idx].pg;
        get_page(pageptr);
-       mutex_unlock(&rp->fetch_lock);
        vmf->page = pageptr;
        return 0;
 }
index 8273126..63a00ff 100644 (file)
@@ -169,8 +169,8 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
 void usb_role_switch_put(struct usb_role_switch *sw)
 {
        if (!IS_ERR_OR_NULL(sw)) {
-               put_device(&sw->dev);
                module_put(sw->dev.parent->driver->owner);
+               put_device(&sw->dev);
        }
 }
 EXPORT_SYMBOL_GPL(usb_role_switch_put);
index 48a4392..9690a5f 100644 (file)
@@ -2901,16 +2901,18 @@ static int edge_startup(struct usb_serial *serial)
        response = 0;
 
        if (edge_serial->is_epic) {
+               struct usb_host_interface *alt;
+
+               alt = serial->interface->cur_altsetting;
+
                /* EPIC thing, set up our interrupt polling now and our read
                 * urb, so that the device knows it really is connected. */
                interrupt_in_found = bulk_in_found = bulk_out_found = false;
-               for (i = 0; i < serial->interface->altsetting[0]
-                                               .desc.bNumEndpoints; ++i) {
+               for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
                        struct usb_endpoint_descriptor *endpoint;
                        int buffer_size;
 
-                       endpoint = &serial->interface->altsetting[0].
-                                                       endpoint[i].desc;
+                       endpoint = &alt->endpoint[i].desc;
                        buffer_size = usb_endpoint_maxp(endpoint);
                        if (!interrupt_in_found &&
                            (usb_endpoint_is_int_in(endpoint))) {
index 66a4dcb..f4c2359 100644 (file)
@@ -135,7 +135,8 @@ static int slave_configure(struct scsi_device *sdev)
         * For such controllers we need to make sure the block layer sets
         * up bounce buffers in addressable memory.
         */
-       if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)))
+       if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) ||
+                       (bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL))
                blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH);
 
        /*
index 7ece6ca..91d6227 100644 (file)
@@ -1612,14 +1612,16 @@ struct typec_port *typec_register_port(struct device *parent,
 
        port->sw = typec_switch_get(&port->dev);
        if (IS_ERR(port->sw)) {
+               ret = PTR_ERR(port->sw);
                put_device(&port->dev);
-               return ERR_CAST(port->sw);
+               return ERR_PTR(ret);
        }
 
        port->mux = typec_mux_get(&port->dev, NULL);
        if (IS_ERR(port->mux)) {
+               ret = PTR_ERR(port->mux);
                put_device(&port->dev);
-               return ERR_CAST(port->mux);
+               return ERR_PTR(ret);
        }
 
        ret = device_add(&port->dev);
index 72481bb..5b986d6 100644 (file)
@@ -32,6 +32,7 @@ endif # TYPEC_TCPCI
 config TYPEC_FUSB302
        tristate "Fairchild FUSB302 Type-C chip driver"
        depends on I2C
+       depends on EXTCON || !EXTCON
        help
          The Fairchild FUSB302 Type-C chip driver that works with
          Type-C Port Controller Manager to provide USB PD and USB
index 6532d68..e4b9667 100644 (file)
@@ -727,6 +727,9 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
 
                        copy -= recv;
                        ret += recv;
+
+                       if (!copy)
+                               break;
                }
 
                if (ret != size)
index 33f8972..00fc987 100644 (file)
@@ -77,16 +77,21 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
        usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
 
        /* recv transfer buffer */
-       if (usbip_recv_xbuff(ud, urb) < 0)
-               return;
+       if (usbip_recv_xbuff(ud, urb) < 0) {
+               urb->status = -EPROTO;
+               goto error;
+       }
 
        /* recv iso_packet_descriptor */
-       if (usbip_recv_iso(ud, urb) < 0)
-               return;
+       if (usbip_recv_iso(ud, urb) < 0) {
+               urb->status = -EPROTO;
+               goto error;
+       }
 
        /* restore the padding in iso packets */
        usbip_pad_iso(ud, urb);
 
+error:
        if (usbip_dbg_flag_vhci_rx)
                usbip_dump_urb(urb);
 
index e05679c..93f995f 100644 (file)
 #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \
                                             __GFP_NOMEMALLOC)
 /* The order of free page blocks to report to host */
-#define VIRTIO_BALLOON_FREE_PAGE_ORDER (MAX_ORDER - 1)
+#define VIRTIO_BALLOON_HINT_BLOCK_ORDER (MAX_ORDER - 1)
 /* The size of a free page block in bytes */
-#define VIRTIO_BALLOON_FREE_PAGE_SIZE \
-       (1 << (VIRTIO_BALLOON_FREE_PAGE_ORDER + PAGE_SHIFT))
+#define VIRTIO_BALLOON_HINT_BLOCK_BYTES \
+       (1 << (VIRTIO_BALLOON_HINT_BLOCK_ORDER + PAGE_SHIFT))
+#define VIRTIO_BALLOON_HINT_BLOCK_PAGES (1 << VIRTIO_BALLOON_HINT_BLOCK_ORDER)
 
 #ifdef CONFIG_BALLOON_COMPACTION
 static struct vfsmount *balloon_mnt;
@@ -380,7 +381,7 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
                if (!page)
                        break;
                free_pages((unsigned long)page_address(page),
-                          VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                          VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        }
        vb->num_free_page_blocks -= num_returned;
        spin_unlock_irq(&vb->free_page_list_lock);
@@ -582,7 +583,7 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                ;
 
        page = alloc_pages(VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG,
-                          VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                          VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        /*
         * When the allocation returns NULL, it indicates that we have got all
         * the possible free pages, so return -EINTR to stop.
@@ -591,13 +592,13 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                return -EINTR;
 
        p = page_address(page);
-       sg_init_one(&sg, p, VIRTIO_BALLOON_FREE_PAGE_SIZE);
+       sg_init_one(&sg, p, VIRTIO_BALLOON_HINT_BLOCK_BYTES);
        /* There is always 1 entry reserved for the cmd id to use. */
        if (vq->num_free > 1) {
                err = virtqueue_add_inbuf(vq, &sg, 1, p, GFP_KERNEL);
                if (unlikely(err)) {
                        free_pages((unsigned long)p,
-                                  VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                                  VIRTIO_BALLOON_HINT_BLOCK_ORDER);
                        return err;
                }
                virtqueue_kick(vq);
@@ -610,7 +611,7 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                 * The vq has no available entry to add this page block, so
                 * just free it.
                 */
-               free_pages((unsigned long)p, VIRTIO_BALLOON_FREE_PAGE_ORDER);
+               free_pages((unsigned long)p, VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        }
 
        return 0;
@@ -721,6 +722,17 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
 
        get_page(newpage); /* balloon reference */
 
+       /*
+         * When we migrate a page to a different zone and adjusted the
+         * managed page count when inflating, we have to fixup the count of
+         * both involved zones.
+         */
+       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) &&
+           page_zone(page) != page_zone(newpage)) {
+               adjust_managed_page_count(page, 1);
+               adjust_managed_page_count(newpage, -1);
+       }
+
        /* balloon's page migration 1st step  -- inflate "newpage" */
        spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
        balloon_page_insert(vb_dev_info, newpage);
@@ -765,11 +777,11 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb,
        unsigned long blocks_to_free, blocks_freed;
 
        pages_to_free = round_up(pages_to_free,
-                                1 << VIRTIO_BALLOON_FREE_PAGE_ORDER);
-       blocks_to_free = pages_to_free >> VIRTIO_BALLOON_FREE_PAGE_ORDER;
+                                VIRTIO_BALLOON_HINT_BLOCK_PAGES);
+       blocks_to_free = pages_to_free / VIRTIO_BALLOON_HINT_BLOCK_PAGES;
        blocks_freed = return_free_pages_to_mm(vb, blocks_to_free);
 
-       return blocks_freed << VIRTIO_BALLOON_FREE_PAGE_ORDER;
+       return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
 }
 
 static unsigned long leak_balloon_pages(struct virtio_balloon *vb,
@@ -826,7 +838,7 @@ static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
        unsigned long count;
 
        count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE;
-       count += vb->num_free_page_blocks << VIRTIO_BALLOON_FREE_PAGE_ORDER;
+       count += vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
 
        return count;
 }
index 4f2e78a..0c142bc 100644 (file)
@@ -394,7 +394,8 @@ static struct notifier_block xen_memory_nb = {
 #else
 static enum bp_state reserve_additional_memory(void)
 {
-       balloon_stats.target_pages = balloon_stats.current_pages;
+       balloon_stats.target_pages = balloon_stats.current_pages +
+                                    balloon_stats.target_unpopulated;
        return BP_ECANCELED;
 }
 #endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
index 49b381e..7b36b51 100644 (file)
@@ -664,7 +664,6 @@ static int grow_gnttab_list(unsigned int more_frames)
        unsigned int nr_glist_frames, new_nr_glist_frames;
        unsigned int grefs_per_frame;
 
-       BUG_ON(gnttab_interface == NULL);
        grefs_per_frame = gnttab_interface->grefs_per_grant_frame;
 
        new_nr_grant_frames = nr_grant_frames + more_frames;
@@ -1160,7 +1159,6 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);
 
 static unsigned int nr_status_frames(unsigned int nr_grant_frames)
 {
-       BUG_ON(gnttab_interface == NULL);
        return gnttab_frames(nr_grant_frames, SPP);
 }
 
@@ -1388,7 +1386,6 @@ static int gnttab_expand(unsigned int req_entries)
        int rc;
        unsigned int cur, extra;
 
-       BUG_ON(gnttab_interface == NULL);
        cur = nr_grant_frames;
        extra = ((req_entries + gnttab_interface->grefs_per_grant_frame - 1) /
                 gnttab_interface->grefs_per_grant_frame);
@@ -1423,7 +1420,6 @@ int gnttab_init(void)
        /* Determine the maximum number of frames required for the
         * grant reference free list on the current hypervisor.
         */
-       BUG_ON(gnttab_interface == NULL);
        max_nr_glist_frames = (max_nr_grant_frames *
                               gnttab_interface->grefs_per_grant_frame / RPP);
 
index d75a238..5f5b8a7 100644 (file)
@@ -116,8 +116,6 @@ int xenbus_probe_devices(struct xen_bus_type *bus);
 
 void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
 
-void xenbus_dev_shutdown(struct device *_dev);
-
 int xenbus_dev_suspend(struct device *dev);
 int xenbus_dev_resume(struct device *dev);
 int xenbus_dev_cancel(struct device *dev);
index c21be6e..378486b 100644 (file)
@@ -255,7 +255,6 @@ fail_put:
        module_put(drv->driver.owner);
 fail:
        xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
-       xenbus_switch_state(dev, XenbusStateClosed);
        return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_probe);
@@ -276,34 +275,20 @@ int xenbus_dev_remove(struct device *_dev)
 
        free_otherend_details(dev);
 
-       xenbus_switch_state(dev, XenbusStateClosed);
+       /*
+        * If the toolstack has forced the device state to closing then set
+        * the state to closed now to allow it to be cleaned up.
+        * Similarly, if the driver does not support re-bind, set the
+        * closed.
+        */
+       if (!drv->allow_rebind ||
+           xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
+               xenbus_switch_state(dev, XenbusStateClosed);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_remove);
 
-void xenbus_dev_shutdown(struct device *_dev)
-{
-       struct xenbus_device *dev = to_xenbus_device(_dev);
-       unsigned long timeout = 5*HZ;
-
-       DPRINTK("%s", dev->nodename);
-
-       get_device(&dev->dev);
-       if (dev->state != XenbusStateConnected) {
-               pr_info("%s: %s: %s != Connected, skipping\n",
-                       __func__, dev->nodename, xenbus_strstate(dev->state));
-               goto out;
-       }
-       xenbus_switch_state(dev, XenbusStateClosing);
-       timeout = wait_for_completion_timeout(&dev->down, timeout);
-       if (!timeout)
-               pr_info("%s: %s timeout closing device\n",
-                       __func__, dev->nodename);
- out:
-       put_device(&dev->dev);
-}
-EXPORT_SYMBOL_GPL(xenbus_dev_shutdown);
-
 int xenbus_register_driver_common(struct xenbus_driver *drv,
                                  struct xen_bus_type *bus,
                                  struct module *owner, const char *mod_name)
index b0bed4f..14876fa 100644 (file)
@@ -198,7 +198,6 @@ static struct xen_bus_type xenbus_backend = {
                .uevent         = xenbus_uevent_backend,
                .probe          = xenbus_dev_probe,
                .remove         = xenbus_dev_remove,
-               .shutdown       = xenbus_dev_shutdown,
                .dev_groups     = xenbus_dev_groups,
        },
 };
index a7d90a7..8a1650b 100644 (file)
@@ -126,6 +126,28 @@ static int xenbus_frontend_dev_probe(struct device *dev)
        return xenbus_dev_probe(dev);
 }
 
+static void xenbus_frontend_dev_shutdown(struct device *_dev)
+{
+       struct xenbus_device *dev = to_xenbus_device(_dev);
+       unsigned long timeout = 5*HZ;
+
+       DPRINTK("%s", dev->nodename);
+
+       get_device(&dev->dev);
+       if (dev->state != XenbusStateConnected) {
+               pr_info("%s: %s: %s != Connected, skipping\n",
+                       __func__, dev->nodename, xenbus_strstate(dev->state));
+               goto out;
+       }
+       xenbus_switch_state(dev, XenbusStateClosing);
+       timeout = wait_for_completion_timeout(&dev->down, timeout);
+       if (!timeout)
+               pr_info("%s: %s timeout closing device\n",
+                       __func__, dev->nodename);
+ out:
+       put_device(&dev->dev);
+}
+
 static const struct dev_pm_ops xenbus_pm_ops = {
        .suspend        = xenbus_dev_suspend,
        .resume         = xenbus_frontend_dev_resume,
@@ -146,7 +168,7 @@ static struct xen_bus_type xenbus_frontend = {
                .uevent         = xenbus_uevent_frontend,
                .probe          = xenbus_frontend_dev_probe,
                .remove         = xenbus_dev_remove,
-               .shutdown       = xenbus_dev_shutdown,
+               .shutdown       = xenbus_frontend_dev_shutdown,
                .dev_groups     = xenbus_dev_groups,
 
                .pm             = &xenbus_pm_ops,
index 4150280..7503899 100644 (file)
@@ -136,6 +136,9 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
 
        ASSERTCMP(d_inode(dentry), ==, NULL);
 
+       if (flags & LOOKUP_CREATE)
+               return ERR_PTR(-EOPNOTSUPP);
+
        if (dentry->d_name.len >= AFSNAMEMAX) {
                _leave(" = -ENAMETOOLONG");
                return ERR_PTR(-ENAMETOOLONG);
index f532d6d..79bc5f1 100644 (file)
@@ -126,7 +126,7 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
                if (src_as->cell)
                        ctx->cell = afs_get_cell(src_as->cell);
 
-               if (size > PAGE_SIZE - 1)
+               if (size < 2 || size > PAGE_SIZE - 1)
                        return -EINVAL;
 
                page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
@@ -140,7 +140,9 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
                }
 
                buf = kmap(page);
-               ret = vfs_parse_fs_string(fc, "source", buf, size);
+               ret = -EINVAL;
+               if (buf[size - 1] == '.')
+                       ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
                kunmap(page);
                put_page(page);
                if (ret < 0)
index fba2ec3..468e171 100644 (file)
@@ -213,13 +213,14 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
 
        /* Display header on line 1 */
        if (v == &cell->proc_volumes) {
-               seq_puts(m, "USE VID      TY\n");
+               seq_puts(m, "USE VID      TY NAME\n");
                return 0;
        }
 
-       seq_printf(m, "%3d %08llx %s\n",
+       seq_printf(m, "%3d %08llx %s %s\n",
                   atomic_read(&vol->usage), vol->vid,
-                  afs_vol_types[vol->type]);
+                  afs_vol_types[vol->type],
+                  vol->name);
 
        return 0;
 }
index 1686bf1..b7f3cb2 100644 (file)
@@ -32,18 +32,11 @@ static void afs_dec_servers_outstanding(struct afs_net *net)
 struct afs_server *afs_find_server(struct afs_net *net,
                                   const struct sockaddr_rxrpc *srx)
 {
-       const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
        const struct afs_addr_list *alist;
        struct afs_server *server = NULL;
        unsigned int i;
-       bool ipv6 = true;
        int seq = 0, diff;
 
-       if (srx->transport.sin6.sin6_addr.s6_addr32[0] == 0 ||
-           srx->transport.sin6.sin6_addr.s6_addr32[1] == 0 ||
-           srx->transport.sin6.sin6_addr.s6_addr32[2] == htonl(0xffff))
-               ipv6 = false;
-
        rcu_read_lock();
 
        do {
@@ -52,7 +45,8 @@ struct afs_server *afs_find_server(struct afs_net *net,
                server = NULL;
                read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
 
-               if (ipv6) {
+               if (srx->transport.family == AF_INET6) {
+                       const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
                        hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
                                alist = rcu_dereference(server->addresses);
                                for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
@@ -68,15 +62,16 @@ struct afs_server *afs_find_server(struct afs_net *net,
                                }
                        }
                } else {
+                       const struct sockaddr_in *a = &srx->transport.sin, *b;
                        hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
                                alist = rcu_dereference(server->addresses);
                                for (i = 0; i < alist->nr_ipv4; i++) {
-                                       b = &alist->addrs[i].transport.sin6;
-                                       diff = ((u16 __force)a->sin6_port -
-                                               (u16 __force)b->sin6_port);
+                                       b = &alist->addrs[i].transport.sin;
+                                       diff = ((u16 __force)a->sin_port -
+                                               (u16 __force)b->sin_port);
                                        if (diff == 0)
-                                               diff = ((u32 __force)a->sin6_addr.s6_addr32[3] -
-                                                       (u32 __force)b->sin6_addr.s6_addr32[3]);
+                                               diff = ((u32 __force)a->sin_addr.s_addr -
+                                                       (u32 __force)b->sin_addr.s_addr);
                                        if (diff == 0)
                                                goto found;
                                }
index 488641b..7f8a9b3 100644 (file)
@@ -404,6 +404,7 @@ static int afs_test_super(struct super_block *sb, struct fs_context *fc)
        return (as->net_ns == fc->net_ns &&
                as->volume &&
                as->volume->vid == ctx->volume->vid &&
+               as->cell == ctx->cell &&
                !as->dyn_root);
 }
 
@@ -448,7 +449,6 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
        /* allocate the root inode and dentry */
        if (as->dyn_root) {
                inode = afs_iget_pseudo_dir(sb, true);
-               sb->s_flags     |= SB_RDONLY;
        } else {
                sprintf(sb->s_id, "%llu", as->volume->vid);
                afs_activate_volume(as->volume);
index 75b6d10..575636f 100644 (file)
@@ -7,6 +7,7 @@ config BTRFS_FS
        select LIBCRC32C
        select CRYPTO_XXHASH
        select CRYPTO_SHA256
+       select CRYPTO_BLAKE2B
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
        select LZO_COMPRESS
index 5b6e86a..24658b5 100644 (file)
@@ -379,7 +379,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
        for (node = rb_first(tm_root); node; node = next) {
                next = rb_next(node);
                tm = rb_entry(node, struct tree_mod_elem, node);
-               if (tm->seq > min_seq)
+               if (tm->seq >= min_seq)
                        continue;
                rb_erase(node, tm_root);
                kfree(tm);
index b2e8fd8..54efb21 100644 (file)
@@ -2787,7 +2787,7 @@ struct btrfs_inode_extref *btrfs_find_name_in_ext_backref(
 /* file-item.c */
 struct btrfs_dio_private;
 int btrfs_del_csums(struct btrfs_trans_handle *trans,
-                   struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
+                   struct btrfs_root *root, u64 bytenr, u64 len);
 blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
                                   u8 *dst);
 blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio,
index 153f71a..274318e 100644 (file)
@@ -1869,8 +1869,8 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                btrfs_pin_extent(fs_info, head->bytenr,
                                 head->num_bytes, 1);
                if (head->is_data) {
-                       ret = btrfs_del_csums(trans, fs_info, head->bytenr,
-                                             head->num_bytes);
+                       ret = btrfs_del_csums(trans, fs_info->csum_root,
+                                             head->bytenr, head->num_bytes);
                }
        }
 
@@ -3175,7 +3175,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                btrfs_release_path(path);
 
                if (is_data) {
-                       ret = btrfs_del_csums(trans, info, bytenr, num_bytes);
+                       ret = btrfs_del_csums(trans, info->csum_root, bytenr,
+                                             num_bytes);
                        if (ret) {
                                btrfs_abort_transaction(trans, ret);
                                goto out;
@@ -3799,6 +3800,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
                                u64 flags, int delalloc)
 {
        int ret = 0;
+       int cache_block_group_error = 0;
        struct btrfs_free_cluster *last_ptr = NULL;
        struct btrfs_block_group *block_group = NULL;
        struct find_free_extent_ctl ffe_ctl = {0};
@@ -3958,7 +3960,20 @@ have_block_group:
                if (unlikely(!ffe_ctl.cached)) {
                        ffe_ctl.have_caching_bg = true;
                        ret = btrfs_cache_block_group(block_group, 0);
-                       BUG_ON(ret < 0);
+
+                       /*
+                        * If we get ENOMEM here or something else we want to
+                        * try other block groups, because it may not be fatal.
+                        * However if we can't find anything else we need to
+                        * save our return here so that we return the actual
+                        * error that caused problems, not ENOSPC.
+                        */
+                       if (ret < 0) {
+                               if (!cache_block_group_error)
+                                       cache_block_group_error = ret;
+                               ret = 0;
+                               goto loop;
+                       }
                        ret = 0;
                }
 
@@ -4045,7 +4060,7 @@ loop:
        if (ret > 0)
                goto search;
 
-       if (ret == -ENOSPC) {
+       if (ret == -ENOSPC && !cache_block_group_error) {
                /*
                 * Use ffe_ctl->total_free_space as fallback if we can't find
                 * any contiguous hole.
@@ -4056,6 +4071,8 @@ loop:
                space_info->max_extent_size = ffe_ctl.max_extent_size;
                spin_unlock(&space_info->lock);
                ins->offset = ffe_ctl.max_extent_size;
+       } else if (ret == -ENOSPC) {
+               ret = cache_block_group_error;
        }
        return ret;
 }
index eb8bd02..2f4802f 100644 (file)
@@ -5074,12 +5074,14 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
                return eb;
        eb = alloc_dummy_extent_buffer(fs_info, start);
        if (!eb)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        eb->fs_info = fs_info;
 again:
        ret = radix_tree_preload(GFP_NOFS);
-       if (ret)
+       if (ret) {
+               exists = ERR_PTR(ret);
                goto free_eb;
+       }
        spin_lock(&fs_info->buffer_lock);
        ret = radix_tree_insert(&fs_info->buffer_radix,
                                start >> PAGE_SHIFT, eb);
index 3270a40..b1bfdc5 100644 (file)
@@ -590,9 +590,9 @@ static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
  * range of bytes.
  */
 int btrfs_del_csums(struct btrfs_trans_handle *trans,
-                   struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
+                   struct btrfs_root *root, u64 bytenr, u64 len)
 {
-       struct btrfs_root *root = fs_info->csum_root;
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_path *path;
        struct btrfs_key key;
        u64 end_byte = bytenr + len;
@@ -602,6 +602,9 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
        int blocksize_bits = fs_info->sb->s_blocksize_bits;
 
+       ASSERT(root == fs_info->csum_root ||
+              root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
index 0cb43b6..8d47c76 100644 (file)
@@ -2599,8 +2599,8 @@ int btrfs_punch_hole_range(struct inode *inode, struct btrfs_path *path,
                        }
                }
 
-               if (clone_info) {
-                       u64 clone_len = drop_end - cur_offset;
+               if (clone_info && drop_end > clone_info->file_offset) {
+                       u64 clone_len = drop_end - clone_info->file_offset;
 
                        ret = btrfs_insert_clone_extent(trans, inode, path,
                                                        clone_info, clone_len);
index 56032c5..e3c7664 100644 (file)
@@ -5728,7 +5728,6 @@ static void inode_tree_add(struct inode *inode)
 
 static void inode_tree_del(struct inode *inode)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int empty = 0;
 
@@ -5741,7 +5740,6 @@ static void inode_tree_del(struct inode *inode)
        spin_unlock(&root->inode_lock);
 
        if (empty && btrfs_root_refs(&root->root_item) == 0) {
-               synchronize_srcu(&fs_info->subvol_srcu);
                spin_lock(&root->inode_lock);
                empty = RB_EMPTY_ROOT(&root->inode_tree);
                spin_unlock(&root->inode_lock);
@@ -9556,9 +9554,8 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        btrfs_init_log_ctx(&ctx_dest, new_inode);
 
        /* close the race window with snapshot create/destroy ioctl */
-       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
-               down_read(&fs_info->subvol_sem);
-       if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (old_ino == BTRFS_FIRST_FREE_OBJECTID ||
+           new_ino == BTRFS_FIRST_FREE_OBJECTID)
                down_read(&fs_info->subvol_sem);
 
        /*
@@ -9792,9 +9789,8 @@ out_fail:
                ret = ret ? ret : ret2;
        }
 out_notrans:
-       if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
-               up_read(&fs_info->subvol_sem);
-       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (new_ino == BTRFS_FIRST_FREE_OBJECTID ||
+           old_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&fs_info->subvol_sem);
 
        ASSERT(list_empty(&ctx_root.list));
index a1ee0b7..18e328c 100644 (file)
@@ -704,11 +704,17 @@ static noinline int create_subvol(struct inode *dir,
 
        btrfs_i_size_write(BTRFS_I(dir), dir->i_size + namelen * 2);
        ret = btrfs_update_inode(trans, root, dir);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               goto fail;
+       }
 
        ret = btrfs_add_root_ref(trans, objectid, root->root_key.objectid,
                                 btrfs_ino(BTRFS_I(dir)), index, name, namelen);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               goto fail;
+       }
 
        ret = btrfs_uuid_tree_add(trans, root_item->uuid,
                                  BTRFS_UUID_KEY_SUBVOL, objectid);
@@ -3720,24 +3726,18 @@ process_slot:
        ret = 0;
 
        if (last_dest_end < destoff + len) {
-               struct btrfs_clone_extent_info clone_info = { 0 };
                /*
-                * We have an implicit hole (NO_HOLES feature is enabled) that
-                * fully or partially overlaps our cloning range at its end.
+                * We have an implicit hole that fully or partially overlaps our
+                * cloning range at its end. This means that we either have the
+                * NO_HOLES feature enabled or the implicit hole happened due to
+                * mixing buffered and direct IO writes against this file.
                 */
                btrfs_release_path(path);
                path->leave_spinning = 0;
 
-               /*
-                * We are dealing with a hole and our clone_info already has a
-                * disk_offset of 0, we only need to fill the data length and
-                * file offset.
-                */
-               clone_info.data_len = destoff + len - last_dest_end;
-               clone_info.file_offset = last_dest_end;
                ret = btrfs_punch_hole_range(inode, path,
                                             last_dest_end, destoff + len - 1,
-                                            &clone_info, &trans);
+                                            NULL, &trans);
                if (ret)
                        goto out;
 
index 93aeb2e..d4282e1 100644 (file)
@@ -3232,12 +3232,12 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
                if (!(fs_info->qgroup_flags &
                      BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup is not enabled");
+                       "qgroup rescan init failed, qgroup rescan is not queued");
                        ret = -EINVAL;
                } else if (!(fs_info->qgroup_flags &
                             BTRFS_QGROUP_STATUS_FLAG_ON)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup rescan is not queued");
+                       "qgroup rescan init failed, qgroup is not enabled");
                        ret = -EINVAL;
                }
 
index d897a8e..c582457 100644 (file)
@@ -4552,6 +4552,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                fs_root = read_fs_root(fs_info, reloc_root->root_key.offset);
                if (IS_ERR(fs_root)) {
                        err = PTR_ERR(fs_root);
+                       list_add_tail(&reloc_root->root_list, &reloc_roots);
                        goto out_free;
                }
 
index ae2db5e..091e5bc 100644 (file)
@@ -7084,12 +7084,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
        spin_unlock(&send_root->root_item_lock);
 
        /*
-        * This is done when we lookup the root, it should already be complete
-        * by the time we get here.
-        */
-       WARN_ON(send_root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE);
-
-       /*
         * Userspace tools do the checks and warn the user if it's
         * not RO.
         */
index 1a846bf..914eea5 100644 (file)
@@ -452,9 +452,9 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
        root->fs_info->tree_root = root;
 
        root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
-       if (!root->node) {
+       if (IS_ERR(root->node)) {
                test_std_err(TEST_ALLOC_EXTENT_BUFFER);
-               ret = -ENOMEM;
+               ret = PTR_ERR(root->node);
                goto out;
        }
        btrfs_set_header_level(root->node, 0);
index 09aaca1..ac035a6 100644 (file)
@@ -484,9 +484,9 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
         * *cough*backref walking code*cough*
         */
        root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
-       if (!root->node) {
+       if (IS_ERR(root->node)) {
                test_err("couldn't allocate dummy buffer");
-               ret = -ENOMEM;
+               ret = PTR_ERR(root->node);
                goto out;
        }
        btrfs_set_header_level(root->node, 0);
index 493d4d9..97f3520 100644 (file)
@@ -227,7 +227,7 @@ static int check_extent_data_item(struct extent_buffer *leaf,
         */
        if (item_size < BTRFS_FILE_EXTENT_INLINE_DATA_START) {
                file_extent_err(leaf, slot,
-                               "invalid item size, have %u expect [%lu, %u)",
+                               "invalid item size, have %u expect [%zu, %u)",
                                item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START,
                                SZ_4K);
                return -EUCLEAN;
@@ -332,7 +332,7 @@ static int check_extent_data_item(struct extent_buffer *leaf,
 }
 
 static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
-                          int slot)
+                          int slot, struct btrfs_key *prev_key)
 {
        struct btrfs_fs_info *fs_info = leaf->fs_info;
        u32 sectorsize = fs_info->sectorsize;
@@ -356,6 +356,20 @@ static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
                        btrfs_item_size_nr(leaf, slot), csumsize);
                return -EUCLEAN;
        }
+       if (slot > 0 && prev_key->type == BTRFS_EXTENT_CSUM_KEY) {
+               u64 prev_csum_end;
+               u32 prev_item_size;
+
+               prev_item_size = btrfs_item_size_nr(leaf, slot - 1);
+               prev_csum_end = (prev_item_size / csumsize) * sectorsize;
+               prev_csum_end += prev_key->offset;
+               if (prev_csum_end > key->offset) {
+                       generic_err(leaf, slot - 1,
+"csum end range (%llu) goes beyond the start range (%llu) of the next csum item",
+                                   prev_csum_end, key->offset);
+                       return -EUCLEAN;
+               }
+       }
        return 0;
 }
 
@@ -1355,7 +1369,7 @@ static int check_leaf_item(struct extent_buffer *leaf,
                ret = check_extent_data_item(leaf, key, slot, prev_key);
                break;
        case BTRFS_EXTENT_CSUM_KEY:
-               ret = check_csum_item(leaf, key, slot);
+               ret = check_csum_item(leaf, key, slot, prev_key);
                break;
        case BTRFS_DIR_ITEM_KEY:
        case BTRFS_DIR_INDEX_KEY:
index 6f75736..d3f1159 100644 (file)
@@ -808,7 +808,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                                                struct btrfs_ordered_sum,
                                                list);
                                if (!ret)
-                                       ret = btrfs_del_csums(trans, fs_info,
+                                       ret = btrfs_del_csums(trans,
+                                                             fs_info->csum_root,
                                                              sums->bytenr,
                                                              sums->len);
                                if (!ret)
@@ -3909,6 +3910,28 @@ static int log_inode_item(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static int log_csums(struct btrfs_trans_handle *trans,
+                    struct btrfs_root *log_root,
+                    struct btrfs_ordered_sum *sums)
+{
+       int ret;
+
+       /*
+        * Due to extent cloning, we might have logged a csum item that covers a
+        * subrange of a cloned extent, and later we can end up logging a csum
+        * item for a larger subrange of the same extent or the entire range.
+        * This would leave csum items in the log tree that cover the same range
+        * and break the searches for checksums in the log tree, resulting in
+        * some checksums missing in the fs/subvolume tree. So just delete (or
+        * trim and adjust) any existing csum items in the log for this range.
+        */
+       ret = btrfs_del_csums(trans, log_root, sums->bytenr, sums->len);
+       if (ret)
+               return ret;
+
+       return btrfs_csum_file_blocks(trans, log_root, sums);
+}
+
 static noinline int copy_items(struct btrfs_trans_handle *trans,
                               struct btrfs_inode *inode,
                               struct btrfs_path *dst_path,
@@ -4054,7 +4077,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                                                   struct btrfs_ordered_sum,
                                                   list);
                if (!ret)
-                       ret = btrfs_csum_file_blocks(trans, log, sums);
+                       ret = log_csums(trans, log, sums);
                list_del(&sums->list);
                kfree(sums);
        }
@@ -4274,7 +4297,7 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
                                                   struct btrfs_ordered_sum,
                                                   list);
                if (!ret)
-                       ret = btrfs_csum_file_blocks(trans, log_root, sums);
+                       ret = log_csums(trans, log_root, sums);
                list_del(&sums->list);
                kfree(sums);
        }
@@ -6294,9 +6317,28 @@ again:
                wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
                if (IS_ERR(wc.replay_dest)) {
                        ret = PTR_ERR(wc.replay_dest);
+
+                       /*
+                        * We didn't find the subvol, likely because it was
+                        * deleted.  This is ok, simply skip this log and go to
+                        * the next one.
+                        *
+                        * We need to exclude the root because we can't have
+                        * other log replays overwriting this log as we'll read
+                        * it back in a few more times.  This will keep our
+                        * block from being modified, and we'll just bail for
+                        * each subsequent pass.
+                        */
+                       if (ret == -ENOENT)
+                               ret = btrfs_pin_extent_for_log_replay(fs_info,
+                                                       log->node->start,
+                                                       log->node->len);
                        free_extent_buffer(log->node);
                        free_extent_buffer(log->commit_root);
                        kfree(log);
+
+                       if (!ret)
+                               goto next;
                        btrfs_handle_fs_error(fs_info, ret,
                                "Couldn't read target root for tree log recovery.");
                        goto error;
@@ -6328,7 +6370,6 @@ again:
                                                  &root->highest_objectid);
                }
 
-               key.offset = found_key.offset - 1;
                wc.replay_dest->log_root = NULL;
                free_extent_buffer(log->node);
                free_extent_buffer(log->commit_root);
@@ -6336,9 +6377,10 @@ again:
 
                if (ret)
                        goto error;
-
+next:
                if (found_key.offset == 0)
                        break;
+               key.offset = found_key.offset - 1;
        }
        btrfs_release_path(path);
 
index 91caab6..76b84f2 100644 (file)
@@ -324,6 +324,8 @@ again_search_slot:
                                }
                                if (ret < 0 && ret != -ENOENT)
                                        goto out;
+                               key.offset++;
+                               goto again_search_slot;
                        }
                        item_size -= sizeof(subid_le);
                        offset += sizeof(subid_le);
index d8e5560..a6d3f08 100644 (file)
@@ -61,7 +61,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID1C3] = {
                .sub_stripes    = 1,
                .dev_stripes    = 1,
-               .devs_max       = 0,
+               .devs_max       = 3,
                .devs_min       = 3,
                .tolerated_failures = 2,
                .devs_increment = 3,
@@ -73,7 +73,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID1C4] = {
                .sub_stripes    = 1,
                .dev_stripes    = 1,
-               .devs_max       = 0,
+               .devs_max       = 4,
                .devs_min       = 4,
                .tolerated_failures = 3,
                .devs_increment = 4,
index f5a3891..9d09bb5 100644 (file)
@@ -1011,18 +1011,13 @@ static int __ceph_is_single_caps(struct ceph_inode_info *ci)
        return rb_first(&ci->i_caps) == rb_last(&ci->i_caps);
 }
 
-static int __ceph_is_any_caps(struct ceph_inode_info *ci)
-{
-       return !RB_EMPTY_ROOT(&ci->i_caps);
-}
-
 int ceph_is_any_caps(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int ret;
 
        spin_lock(&ci->i_ceph_lock);
-       ret = __ceph_is_any_caps(ci);
+       ret = __ceph_is_any_real_caps(ci);
        spin_unlock(&ci->i_ceph_lock);
 
        return ret;
@@ -1099,15 +1094,16 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
        if (removed)
                ceph_put_cap(mdsc, cap);
 
-       /* when reconnect denied, we remove session caps forcibly,
-        * i_wr_ref can be non-zero. If there are ongoing write,
-        * keep i_snap_realm.
-        */
-       if (!__ceph_is_any_caps(ci) && ci->i_wr_ref == 0 && ci->i_snap_realm)
-               drop_inode_snap_realm(ci);
+       if (!__ceph_is_any_real_caps(ci)) {
+               /* when reconnect denied, we remove session caps forcibly,
+                * i_wr_ref can be non-zero. If there are ongoing write,
+                * keep i_snap_realm.
+                */
+               if (ci->i_wr_ref == 0 && ci->i_snap_realm)
+                       drop_inode_snap_realm(ci);
 
-       if (!__ceph_is_any_real_caps(ci))
                __cap_delay_cancel(mdsc, ci);
+       }
 }
 
 struct cap_msg_args {
@@ -2764,7 +2760,19 @@ int ceph_get_caps(struct file *filp, int need, int want,
                if (ret == -EAGAIN)
                        continue;
                if (!ret) {
+                       struct ceph_mds_client *mdsc = fsc->mdsc;
+                       struct cap_wait cw;
                        DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+                       cw.ino = inode->i_ino;
+                       cw.tgid = current->tgid;
+                       cw.need = need;
+                       cw.want = want;
+
+                       spin_lock(&mdsc->caps_list_lock);
+                       list_add(&cw.list, &mdsc->cap_wait_list);
+                       spin_unlock(&mdsc->caps_list_lock);
+
                        add_wait_queue(&ci->i_cap_wq, &wait);
 
                        flags |= NON_BLOCKING;
@@ -2778,6 +2786,11 @@ int ceph_get_caps(struct file *filp, int need, int want,
                        }
 
                        remove_wait_queue(&ci->i_cap_wq, &wait);
+
+                       spin_lock(&mdsc->caps_list_lock);
+                       list_del(&cw.list);
+                       spin_unlock(&mdsc->caps_list_lock);
+
                        if (ret == -EAGAIN)
                                continue;
                }
@@ -2928,7 +2941,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
                                ci->i_head_snapc = NULL;
                        }
                        /* see comment in __ceph_remove_cap() */
-                       if (!__ceph_is_any_caps(ci) && ci->i_snap_realm)
+                       if (!__ceph_is_any_real_caps(ci) && ci->i_snap_realm)
                                drop_inode_snap_realm(ci);
                }
        spin_unlock(&ci->i_ceph_lock);
index facb387..c281f32 100644 (file)
@@ -139,6 +139,7 @@ static int caps_show(struct seq_file *s, void *p)
        struct ceph_fs_client *fsc = s->private;
        struct ceph_mds_client *mdsc = fsc->mdsc;
        int total, avail, used, reserved, min, i;
+       struct cap_wait *cw;
 
        ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
        seq_printf(s, "total\t\t%d\n"
@@ -166,6 +167,18 @@ static int caps_show(struct seq_file *s, void *p)
        }
        mutex_unlock(&mdsc->mutex);
 
+       seq_printf(s, "\n\nWaiters:\n--------\n");
+       seq_printf(s, "tgid         ino                need             want\n");
+       seq_printf(s, "-----------------------------------------------------\n");
+
+       spin_lock(&mdsc->caps_list_lock);
+       list_for_each_entry(cw, &mdsc->cap_wait_list, list) {
+               seq_printf(s, "%-13d0x%-17lx%-17s%-17s\n", cw->tgid, cw->ino,
+                               ceph_cap_string(cw->need),
+                               ceph_cap_string(cw->want));
+       }
+       spin_unlock(&mdsc->caps_list_lock);
+
        return 0;
 }
 
index 068b029..374db1b 100644 (file)
@@ -2015,7 +2015,7 @@ void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr)
        if (!nr)
                return;
        val = atomic_add_return(nr, &mdsc->cap_reclaim_pending);
-       if (!(val % CEPH_CAPS_PER_RELEASE)) {
+       if ((val % CEPH_CAPS_PER_RELEASE) < nr) {
                atomic_set(&mdsc->cap_reclaim_pending, 0);
                ceph_queue_cap_reclaim_work(mdsc);
        }
@@ -2032,12 +2032,13 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
        struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
        struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
        size_t size = sizeof(struct ceph_mds_reply_dir_entry);
-       int order, num_entries;
+       unsigned int num_entries;
+       int order;
 
        spin_lock(&ci->i_ceph_lock);
        num_entries = ci->i_files + ci->i_subdirs;
        spin_unlock(&ci->i_ceph_lock);
-       num_entries = max(num_entries, 1);
+       num_entries = max(num_entries, 1U);
        num_entries = min(num_entries, opt->max_readdir);
 
        order = get_order(size * num_entries);
@@ -4168,6 +4169,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        INIT_DELAYED_WORK(&mdsc->delayed_work, delayed_work);
        mdsc->last_renew_caps = jiffies;
        INIT_LIST_HEAD(&mdsc->cap_delay_list);
+       INIT_LIST_HEAD(&mdsc->cap_wait_list);
        spin_lock_init(&mdsc->cap_delay_lock);
        INIT_LIST_HEAD(&mdsc->snap_flush_list);
        spin_lock_init(&mdsc->snap_flush_lock);
index 5cd131b..14c7e8c 100644 (file)
@@ -340,6 +340,14 @@ struct ceph_quotarealm_inode {
        struct inode *inode;
 };
 
+struct cap_wait {
+       struct list_head        list;
+       unsigned long           ino;
+       pid_t                   tgid;
+       int                     need;
+       int                     want;
+};
+
 /*
  * mds client state
  */
@@ -416,6 +424,7 @@ struct ceph_mds_client {
        spinlock_t      caps_list_lock;
        struct          list_head caps_list; /* unused (reserved or
                                                unreserved) */
+       struct          list_head cap_wait_list;
        int             caps_total_count;    /* total caps allocated */
        int             caps_use_count;      /* in use */
        int             caps_use_max;        /* max used caps */
index aeec1d6..471bac3 100644 (file)
@@ -158,6 +158,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                void *pexport_targets = NULL;
                struct ceph_timespec laggy_since;
                struct ceph_mds_info *info;
+               bool laggy;
 
                ceph_decode_need(p, end, sizeof(u64) + 1, bad);
                global_id = ceph_decode_64(p);
@@ -190,6 +191,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                if (err)
                        goto corrupt;
                ceph_decode_copy(p, &laggy_since, sizeof(laggy_since));
+               laggy = laggy_since.tv_sec != 0 || laggy_since.tv_nsec != 0;
                *p += sizeof(u32);
                ceph_decode_32_safe(p, end, namelen, bad);
                *p += namelen;
@@ -207,10 +209,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                        *p = info_end;
                }
 
-               dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
+               dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n",
                     i+1, n, global_id, mds, inc,
                     ceph_pr_addr(&addr),
-                    ceph_mds_state_name(state));
+                    ceph_mds_state_name(state),
+                    laggy ? "(laggy)" : "");
 
                if (mds < 0 || state <= 0)
                        continue;
@@ -230,8 +233,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                info->global_id = global_id;
                info->state = state;
                info->addr = addr;
-               info->laggy = (laggy_since.tv_sec != 0 ||
-                              laggy_since.tv_nsec != 0);
+               info->laggy = laggy;
                info->num_export_targets = num_export_targets;
                if (num_export_targets) {
                        info->export_targets = kcalloc(num_export_targets,
@@ -355,6 +357,8 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                m->m_damaged = false;
        }
 bad_ext:
+       dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
+            !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
        *p = end;
        dout("mdsmap_decode success epoch %u\n", m->m_epoch);
        return m;
index 9c9a7c6..29a795f 100644 (file)
@@ -172,10 +172,10 @@ static const struct fs_parameter_enum ceph_mount_param_enums[] = {
 static const struct fs_parameter_spec ceph_mount_param_specs[] = {
        fsparam_flag_no ("acl",                         Opt_acl),
        fsparam_flag_no ("asyncreaddir",                Opt_asyncreaddir),
-       fsparam_u32     ("caps_max",                    Opt_caps_max),
+       fsparam_s32     ("caps_max",                    Opt_caps_max),
        fsparam_u32     ("caps_wanted_delay_max",       Opt_caps_wanted_delay_max),
        fsparam_u32     ("caps_wanted_delay_min",       Opt_caps_wanted_delay_min),
-       fsparam_s32     ("write_congestion_kb",         Opt_congestion_kb),
+       fsparam_u32     ("write_congestion_kb",         Opt_congestion_kb),
        fsparam_flag_no ("copyfrom",                    Opt_copyfrom),
        fsparam_flag_no ("dcache",                      Opt_dcache),
        fsparam_flag_no ("dirstat",                     Opt_dirstat),
@@ -187,8 +187,8 @@ static const struct fs_parameter_spec ceph_mount_param_specs[] = {
        fsparam_flag_no ("quotadf",                     Opt_quotadf),
        fsparam_u32     ("rasize",                      Opt_rasize),
        fsparam_flag_no ("rbytes",                      Opt_rbytes),
-       fsparam_s32     ("readdir_max_bytes",           Opt_readdir_max_bytes),
-       fsparam_s32     ("readdir_max_entries",         Opt_readdir_max_entries),
+       fsparam_u32     ("readdir_max_bytes",           Opt_readdir_max_bytes),
+       fsparam_u32     ("readdir_max_entries",         Opt_readdir_max_entries),
        fsparam_enum    ("recover_session",             Opt_recover_session),
        fsparam_flag_no ("require_active_mds",          Opt_require_active_mds),
        fsparam_u32     ("rsize",                       Opt_rsize),
@@ -328,7 +328,9 @@ static int ceph_parse_mount_param(struct fs_context *fc,
                fsopt->caps_wanted_delay_max = result.uint_32;
                break;
        case Opt_caps_max:
-               fsopt->caps_max = result.uint_32;
+               if (result.int_32 < 0)
+                       goto out_of_range;
+               fsopt->caps_max = result.int_32;
                break;
        case Opt_readdir_max_entries:
                if (result.uint_32 < 1)
@@ -547,25 +549,25 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_show_option(m, "recover_session", "clean");
 
        if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
-               seq_printf(m, ",wsize=%d", fsopt->wsize);
+               seq_printf(m, ",wsize=%u", fsopt->wsize);
        if (fsopt->rsize != CEPH_MAX_READ_SIZE)
-               seq_printf(m, ",rsize=%d", fsopt->rsize);
+               seq_printf(m, ",rsize=%u", fsopt->rsize);
        if (fsopt->rasize != CEPH_RASIZE_DEFAULT)
-               seq_printf(m, ",rasize=%d", fsopt->rasize);
+               seq_printf(m, ",rasize=%u", fsopt->rasize);
        if (fsopt->congestion_kb != default_congestion_kb())
-               seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
+               seq_printf(m, ",write_congestion_kb=%u", fsopt->congestion_kb);
        if (fsopt->caps_max)
                seq_printf(m, ",caps_max=%d", fsopt->caps_max);
        if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_min=%d",
+               seq_printf(m, ",caps_wanted_delay_min=%u",
                         fsopt->caps_wanted_delay_min);
        if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_max=%d",
+               seq_printf(m, ",caps_wanted_delay_max=%u",
                           fsopt->caps_wanted_delay_max);
        if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
-               seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
+               seq_printf(m, ",readdir_max_entries=%u", fsopt->max_readdir);
        if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
-               seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
+               seq_printf(m, ",readdir_max_bytes=%u", fsopt->max_readdir_bytes);
        if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
                seq_show_option(m, "snapdirname", fsopt->snapdir_name);
 
index f0f9cb7..3bf1a01 100644 (file)
 #define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
 
 struct ceph_mount_options {
-       int flags;
+       unsigned int flags;
 
-       int wsize;            /* max write size */
-       int rsize;            /* max read size */
-       int rasize;           /* max readahead */
-       int congestion_kb;    /* max writeback in flight */
-       int caps_wanted_delay_min, caps_wanted_delay_max;
+       unsigned int wsize;            /* max write size */
+       unsigned int rsize;            /* max read size */
+       unsigned int rasize;           /* max readahead */
+       unsigned int congestion_kb;    /* max writeback in flight */
+       unsigned int caps_wanted_delay_min, caps_wanted_delay_max;
        int caps_max;
-       int max_readdir;       /* max readdir result (entires) */
-       int max_readdir_bytes; /* max readdir result (bytes) */
+       unsigned int max_readdir;       /* max readdir result (entries) */
+       unsigned int max_readdir_bytes; /* max readdir result (bytes) */
 
        /*
         * everything above this point can be memcmp'd; everything below
index fd0262c..ce9bac7 100644 (file)
@@ -1061,7 +1061,7 @@ cap_unix(struct cifs_ses *ses)
 struct cached_fid {
        bool is_valid:1;        /* Do we have a useable root fid */
        bool file_all_info_is_valid:1;
-
+       bool has_lease:1;
        struct kref refcount;
        struct cifs_fid *fid;
        struct mutex fid_mutex;
index 4f554f0..cc86a67 100644 (file)
@@ -42,6 +42,7 @@
 #include "cifsproto.h"
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
+#include "smb2proto.h"
 #include "fscache.h"
 #include "smbdirect.h"
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -112,6 +113,8 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
 
        mutex_lock(&tcon->crfid.fid_mutex);
        tcon->crfid.is_valid = false;
+       /* cached handle is not valid, so SMB2_CLOSE won't be sent below */
+       close_shroot_lease_locked(&tcon->crfid);
        memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
        mutex_unlock(&tcon->crfid.fid_mutex);
 
index 18c7a33..5ef5e97 100644 (file)
@@ -95,6 +95,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                goto finished;
        }
 
+       memset(&oparms, 0, sizeof(struct cifs_open_parms));
        oparms.tcon = tcon;
        oparms.desired_access = desired_access;
        oparms.disposition = create_disposition;
index a5c96bc..6250370 100644 (file)
@@ -616,6 +616,7 @@ smb2_close_cached_fid(struct kref *ref)
                           cfid->fid->volatile_fid);
                cfid->is_valid = false;
                cfid->file_all_info_is_valid = false;
+               cfid->has_lease = false;
        }
 }
 
@@ -626,13 +627,28 @@ void close_shroot(struct cached_fid *cfid)
        mutex_unlock(&cfid->fid_mutex);
 }
 
+void close_shroot_lease_locked(struct cached_fid *cfid)
+{
+       if (cfid->has_lease) {
+               cfid->has_lease = false;
+               kref_put(&cfid->refcount, smb2_close_cached_fid);
+       }
+}
+
+void close_shroot_lease(struct cached_fid *cfid)
+{
+       mutex_lock(&cfid->fid_mutex);
+       close_shroot_lease_locked(cfid);
+       mutex_unlock(&cfid->fid_mutex);
+}
+
 void
 smb2_cached_lease_break(struct work_struct *work)
 {
        struct cached_fid *cfid = container_of(work,
                                struct cached_fid, lease_break);
 
-       close_shroot(cfid);
+       close_shroot_lease(cfid);
 }
 
 /*
@@ -773,6 +789,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
        /* BB TBD check to see if oplock level check can be removed below */
        if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
                kref_get(&tcon->crfid.refcount);
+               tcon->crfid.has_lease = true;
                smb2_parse_contexts(server, o_rsp,
                                &oparms.fid->epoch,
                                oparms.fid->lease_key, &oplock, NULL);
index 0ab6b12..9434f6d 100644 (file)
@@ -1847,7 +1847,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
        if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
                return 0;
 
-       close_shroot(&tcon->crfid);
+       close_shroot_lease(&tcon->crfid);
 
        rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req,
                             &total_len);
index a18272c..27d29f2 100644 (file)
@@ -70,6 +70,8 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server,
 extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
                        struct cifs_fid *pfid);
 extern void close_shroot(struct cached_fid *cfid);
+extern void close_shroot_lease(struct cached_fid *cfid);
+extern void close_shroot_lease_locked(struct cached_fid *cfid);
 extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
                                   struct smb2_file_all_info *src);
 extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
index 040df1f..40cca35 100644 (file)
@@ -151,7 +151,7 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
 }
 
 #define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE    \
-       (CONST_STRLEN("fscrypt-") + FIELD_SIZEOF(struct super_block, s_id))
+       (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
 
 #define FSCRYPT_MK_DESCRIPTION_SIZE    (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
 
index a13a787..b766c3e 100644 (file)
@@ -649,6 +649,8 @@ ssize_t erofs_listxattr(struct dentry *dentry,
        struct listxattr_iter it;
 
        ret = init_inode_xattrs(d_inode(dentry));
+       if (ret == -ENOATTR)
+               return 0;
        if (ret)
                return ret;
 
index 92a9da1..bbce1c3 100644 (file)
@@ -25,7 +25,7 @@
  * For constructing the negative timestamp lower bound value.
  * binary: 10000000 00000000 00000000 00000000
  */
-#define LOWER_MSB_1 (-0x80000000L)
+#define LOWER_MSB_1 (-(UPPER_MSB_0) - 1L)  /* avoid overflow */
 /*
  * For constructing the negative timestamp upper bound value.
  * binary: 11111111 11111111 11111111 11111111
index 3da91a1..2f4fcf9 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -960,7 +960,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
        return ksys_dup3(oldfd, newfd, 0);
 }
 
-int ksys_dup(unsigned int fildes)
+SYSCALL_DEFINE1(dup, unsigned int, fildes)
 {
        int ret = -EBADF;
        struct file *file = fget_raw(fildes);
@@ -975,11 +975,6 @@ int ksys_dup(unsigned int fildes)
        return ret;
 }
 
-SYSCALL_DEFINE1(dup, unsigned int, fildes)
-{
-       return ksys_dup(fildes);
-}
-
 int f_dupfd(unsigned int from, struct file *file, unsigned flags)
 {
        int err;
index 74b4050..11e80b7 100644 (file)
@@ -49,7 +49,6 @@ struct io_worker {
        struct hlist_nulls_node nulls_node;
        struct list_head all_list;
        struct task_struct *task;
-       wait_queue_head_t wait;
        struct io_wqe *wqe;
 
        struct io_wq_work *cur_work;
@@ -258,7 +257,7 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
 
        worker = hlist_nulls_entry(n, struct io_worker, nulls_node);
        if (io_worker_get(worker)) {
-               wake_up(&worker->wait);
+               wake_up_process(worker->task);
                io_worker_release(worker);
                return true;
        }
@@ -492,28 +491,46 @@ 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;
-       DEFINE_WAIT(wait);
+       bool did_work;
 
        io_worker_start(wqe, worker);
 
+       did_work = false;
        while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
-               prepare_to_wait(&worker->wait, &wait, TASK_INTERRUPTIBLE);
-
+               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);
-                       continue;
+                       did_work = true;
+                       goto loop;
                }
+               did_work = false;
                /* drops the lock on success, retry */
                if (__io_worker_idle(wqe, worker)) {
                        __release(&wqe->lock);
-                       continue;
+                       goto loop;
                }
                spin_unlock_irq(&wqe->lock);
                if (signal_pending(current))
@@ -526,8 +543,6 @@ static int io_wqe_worker(void *data)
                        break;
        }
 
-       finish_wait(&worker->wait, &wait);
-
        if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
                spin_lock_irq(&wqe->lock);
                if (!wq_list_empty(&wqe->work_list))
@@ -589,7 +604,6 @@ static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
 
        refcount_set(&worker->ref, 1);
        worker->nulls_node.pprev = NULL;
-       init_waitqueue_head(&worker->wait);
        worker->wqe = wqe;
        spin_lock_init(&worker->lock);
 
@@ -934,7 +948,7 @@ static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
        /*
         * Now check if a free (going busy) or busy worker has the work
         * currently running. If we find it there, we'll return CANCEL_RUNNING
-        * as an indication that we attempte to signal cancellation. The
+        * as an indication that we attempt to signal cancellation. The
         * completion will run normally in this case.
         */
        rcu_read_lock();
index 7c333a2..3f5e356 100644 (file)
@@ -35,7 +35,8 @@ static inline void wq_list_add_tail(struct io_wq_work_node *node,
                                    struct io_wq_work_list *list)
 {
        if (!list->first) {
-               list->first = list->last = node;
+               list->last = node;
+               WRITE_ONCE(list->first, node);
        } else {
                list->last->next = node;
                list->last = node;
@@ -47,7 +48,7 @@ static inline void wq_node_del(struct io_wq_work_list *list,
                               struct io_wq_work_node *prev)
 {
        if (node == list->first)
-               list->first = node->next;
+               WRITE_ONCE(list->first, node->next);
        if (node == list->last)
                list->last = prev;
        if (prev)
@@ -58,7 +59,7 @@ static inline void wq_node_del(struct io_wq_work_list *list,
 #define wq_list_for_each(pos, prv, head)                       \
        for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next)
 
-#define wq_list_empty(list)    ((list)->first == NULL)
+#define wq_list_empty(list)    (READ_ONCE((list)->first) == NULL)
 #define INIT_WQ_LIST(list)     do {                            \
        (list)->first = NULL;                                   \
        (list)->last = NULL;                                    \
@@ -119,6 +120,10 @@ static inline void io_wq_worker_sleeping(struct task_struct *tsk)
 static inline void io_wq_worker_running(struct task_struct *tsk)
 {
 }
-#endif /* CONFIG_IO_WQ */
+#endif
 
-#endif /* INTERNAL_IO_WQ_H */
+static inline bool io_wq_current_is_worker(void)
+{
+       return in_task() && (current->flags & PF_IO_WORKER);
+}
+#endif
index 405be10..6f084e3 100644 (file)
@@ -289,11 +289,14 @@ struct io_ring_ctx {
  */
 struct io_poll_iocb {
        struct file                     *file;
-       struct wait_queue_head          *head;
+       union {
+               struct wait_queue_head  *head;
+               u64                     addr;
+       };
        __poll_t                        events;
        bool                            done;
        bool                            canceled;
-       struct wait_queue_entry         *wait;
+       struct wait_queue_entry         wait;
 };
 
 struct io_timeout_data {
@@ -304,6 +307,31 @@ struct io_timeout_data {
        u32                             seq_offset;
 };
 
+struct io_accept {
+       struct file                     *file;
+       struct sockaddr __user          *addr;
+       int __user                      *addr_len;
+       int                             flags;
+};
+
+struct io_sync {
+       struct file                     *file;
+       loff_t                          len;
+       loff_t                          off;
+       int                             flags;
+};
+
+struct io_cancel {
+       struct file                     *file;
+       u64                             addr;
+};
+
+struct io_timeout {
+       struct file                     *file;
+       u64                             addr;
+       int                             flags;
+};
+
 struct io_async_connect {
        struct sockaddr_storage         address;
 };
@@ -343,6 +371,10 @@ struct io_kiocb {
                struct file             *file;
                struct kiocb            rw;
                struct io_poll_iocb     poll;
+               struct io_accept        accept;
+               struct io_sync          sync;
+               struct io_cancel        cancel;
+               struct io_timeout       timeout;
        };
 
        const struct io_uring_sqe       *sqe;
@@ -352,6 +384,7 @@ struct io_kiocb {
        bool                            has_user;
        bool                            in_async;
        bool                            needs_fixed_file;
+       u8                              opcode;
 
        struct io_ring_ctx      *ctx;
        union {
@@ -377,6 +410,8 @@ struct io_kiocb {
 #define REQ_F_TIMEOUT_NOSEQ    8192    /* no timeout sequence */
 #define REQ_F_INFLIGHT         16384   /* on inflight list */
 #define REQ_F_COMP_LOCKED      32768   /* completion under lock */
+#define REQ_F_HARDLINK         65536   /* doesn't sever on completion < 0 */
+#define REQ_F_PREPPED          131072  /* request already opcode prepared */
        u64                     user_data;
        u32                     result;
        u32                     sequence;
@@ -563,12 +598,10 @@ static void __io_commit_cqring(struct io_ring_ctx *ctx)
        }
 }
 
-static inline bool io_sqe_needs_user(const struct io_uring_sqe *sqe)
+static inline bool io_req_needs_user(struct io_kiocb *req)
 {
-       u8 opcode = READ_ONCE(sqe->opcode);
-
-       return !(opcode == IORING_OP_READ_FIXED ||
-                opcode == IORING_OP_WRITE_FIXED);
+       return !(req->opcode == IORING_OP_READ_FIXED ||
+                req->opcode == IORING_OP_WRITE_FIXED);
 }
 
 static inline bool io_prep_async_work(struct io_kiocb *req,
@@ -577,10 +610,12 @@ static inline bool io_prep_async_work(struct io_kiocb *req,
        bool do_hashed = false;
 
        if (req->sqe) {
-               switch (req->sqe->opcode) {
+               switch (req->opcode) {
                case IORING_OP_WRITEV:
                case IORING_OP_WRITE_FIXED:
-                       do_hashed = true;
+                       /* only regular files should be hashed for writes */
+                       if (req->flags & REQ_F_ISREG)
+                               do_hashed = true;
                        /* fall-through */
                case IORING_OP_READV:
                case IORING_OP_READ_FIXED:
@@ -598,7 +633,7 @@ static inline bool io_prep_async_work(struct io_kiocb *req,
                                req->work.flags |= IO_WQ_WORK_UNBOUND;
                        break;
                }
-               if (io_sqe_needs_user(req->sqe))
+               if (io_req_needs_user(req))
                        req->work.flags |= IO_WQ_WORK_NEEDS_USER;
        }
 
@@ -969,7 +1004,7 @@ static void io_fail_links(struct io_kiocb *req)
                trace_io_uring_fail_link(req, link);
 
                if ((req->flags & REQ_F_LINK_TIMEOUT) &&
-                   link->sqe->opcode == IORING_OP_LINK_TIMEOUT) {
+                   link->opcode == IORING_OP_LINK_TIMEOUT) {
                        io_link_cancel_timeout(link);
                } else {
                        io_cqring_fill_event(link, -ECANCELED);
@@ -1175,7 +1210,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 }
 
 /*
- * Poll for a mininum of 'min' events. Note that if min == 0 we consider that a
+ * Poll for a minimum of 'min' events. Note that if min == 0 we consider that a
  * non-spinning poll check - we'll still enter the driver poll loop, but only
  * as a non-spinning completion check.
  */
@@ -1292,6 +1327,12 @@ static void kiocb_end_write(struct io_kiocb *req)
        file_end_write(req->file);
 }
 
+static inline void req_set_fail_links(struct io_kiocb *req)
+{
+       if ((req->flags & (REQ_F_LINK | REQ_F_HARDLINK)) == REQ_F_LINK)
+               req->flags |= REQ_F_FAIL_LINK;
+}
+
 static void io_complete_rw_common(struct kiocb *kiocb, long res)
 {
        struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw);
@@ -1299,8 +1340,8 @@ static void io_complete_rw_common(struct kiocb *kiocb, long res)
        if (kiocb->ki_flags & IOCB_WRITE)
                kiocb_end_write(req);
 
-       if ((req->flags & REQ_F_LINK) && res != req->result)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (res != req->result)
+               req_set_fail_links(req);
        io_cqring_add_event(req, res);
 }
 
@@ -1330,8 +1371,8 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2)
        if (kiocb->ki_flags & IOCB_WRITE)
                kiocb_end_write(req);
 
-       if ((req->flags & REQ_F_LINK) && res != req->result)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (res != req->result)
+               req_set_fail_links(req);
        req->result = res;
        if (res != -EAGAIN)
                req->flags |= REQ_F_IOPOLL_COMPLETED;
@@ -1422,7 +1463,7 @@ static bool io_file_supports_async(struct file *file)
 {
        umode_t mode = file_inode(file)->i_mode;
 
-       if (S_ISBLK(mode) || S_ISCHR(mode))
+       if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISSOCK(mode))
                return true;
        if (S_ISREG(mode) && file->f_op != &io_uring_fops)
                return true;
@@ -1606,7 +1647,7 @@ static ssize_t io_import_iovec(int rw, struct io_kiocb *req,
         * for that purpose and instead let the caller pass in the read/write
         * flag.
         */
-       opcode = READ_ONCE(sqe->opcode);
+       opcode = req->opcode;
        if (opcode == IORING_OP_READ_FIXED || opcode == IORING_OP_WRITE_FIXED) {
                *iovec = NULL;
                return io_import_fixed(req->ctx, rw, sqe, iter);
@@ -1692,7 +1733,7 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
        return ret;
 }
 
-static void io_req_map_io(struct io_kiocb *req, ssize_t io_size,
+static void io_req_map_rw(struct io_kiocb *req, ssize_t io_size,
                          struct iovec *iovec, struct iovec *fast_iov,
                          struct iov_iter *iter)
 {
@@ -1706,19 +1747,39 @@ static void io_req_map_io(struct io_kiocb *req, ssize_t io_size,
        }
 }
 
-static int io_setup_async_io(struct io_kiocb *req, ssize_t io_size,
-                            struct iovec *iovec, struct iovec *fast_iov,
-                            struct iov_iter *iter)
+static int io_alloc_async_ctx(struct io_kiocb *req)
 {
        req->io = kmalloc(sizeof(*req->io), GFP_KERNEL);
        if (req->io) {
-               io_req_map_io(req, io_size, iovec, fast_iov, iter);
                memcpy(&req->io->sqe, req->sqe, sizeof(req->io->sqe));
                req->sqe = &req->io->sqe;
                return 0;
        }
 
-       return -ENOMEM;
+       return 1;
+}
+
+static void io_rw_async(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct iovec *iov = NULL;
+
+       if (req->io->rw.iov != req->io->rw.fast_iov)
+               iov = req->io->rw.iov;
+       io_wq_submit_work(workptr);
+       kfree(iov);
+}
+
+static int io_setup_async_rw(struct io_kiocb *req, ssize_t io_size,
+                            struct iovec *iovec, struct iovec *fast_iov,
+                            struct iov_iter *iter)
+{
+       if (!req->io && io_alloc_async_ctx(req))
+               return -ENOMEM;
+
+       io_req_map_rw(req, io_size, iovec, fast_iov, iter);
+       req->work.func = io_rw_async;
+       return 0;
 }
 
 static int io_read_prep(struct io_kiocb *req, struct iovec **iovec,
@@ -1756,6 +1817,10 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
                        return ret;
        }
 
+       /* Ensure we clear previously set non-block flag */
+       if (!force_nonblock)
+               req->rw.ki_flags &= ~IOCB_NOWAIT;
+
        file = req->file;
        io_size = ret;
        if (req->flags & REQ_F_LINK)
@@ -1797,7 +1862,7 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
                        kiocb_done(kiocb, ret2, nxt, req->in_async);
                } else {
 copy_iov:
-                       ret = io_setup_async_io(req, io_size, iovec,
+                       ret = io_setup_async_rw(req, io_size, iovec,
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
@@ -1805,7 +1870,8 @@ copy_iov:
                }
        }
 out_free:
-       kfree(iovec);
+       if (!io_wq_current_is_worker())
+               kfree(iovec);
        return ret;
 }
 
@@ -1844,6 +1910,10 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                        return ret;
        }
 
+       /* Ensure we clear previously set non-block flag */
+       if (!force_nonblock)
+               req->rw.ki_flags &= ~IOCB_NOWAIT;
+
        file = kiocb->ki_filp;
        io_size = ret;
        if (req->flags & REQ_F_LINK)
@@ -1858,7 +1928,9 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                goto copy_iov;
        }
 
-       if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT))
+       /* file path doesn't support NOWAIT for non-direct_IO */
+       if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT) &&
+           (req->flags & REQ_F_ISREG))
                goto copy_iov;
 
        iov_count = iov_iter_count(&iter);
@@ -1889,7 +1961,7 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                        kiocb_done(kiocb, ret2, nxt, req->in_async);
                } else {
 copy_iov:
-                       ret = io_setup_async_io(req, io_size, iovec,
+                       ret = io_setup_async_rw(req, io_size, iovec,
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
@@ -1897,7 +1969,8 @@ copy_iov:
                }
        }
 out_free:
-       kfree(iovec);
+       if (!io_wq_current_is_worker())
+               kfree(iovec);
        return ret;
 }
 
@@ -1916,10 +1989,13 @@ static int io_nop(struct io_kiocb *req)
        return 0;
 }
 
-static int io_prep_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_prep_fsync(struct io_kiocb *req)
 {
+       const struct io_uring_sqe *sqe = req->sqe;
        struct io_ring_ctx *ctx = req->ctx;
 
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
        if (!req->file)
                return -EBADF;
 
@@ -1928,46 +2004,80 @@ static int io_prep_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (unlikely(sqe->addr || sqe->ioprio || sqe->buf_index))
                return -EINVAL;
 
+       req->sync.flags = READ_ONCE(sqe->fsync_flags);
+       if (unlikely(req->sync.flags & ~IORING_FSYNC_DATASYNC))
+               return -EINVAL;
+
+       req->sync.off = READ_ONCE(sqe->off);
+       req->sync.len = READ_ONCE(sqe->len);
+       req->flags |= REQ_F_PREPPED;
        return 0;
 }
 
-static int io_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                   struct io_kiocb **nxt, bool force_nonblock)
+static bool io_req_cancelled(struct io_kiocb *req)
 {
-       loff_t sqe_off = READ_ONCE(sqe->off);
-       loff_t sqe_len = READ_ONCE(sqe->len);
-       loff_t end = sqe_off + sqe_len;
-       unsigned fsync_flags;
+       if (req->work.flags & IO_WQ_WORK_CANCEL) {
+               req_set_fail_links(req);
+               io_cqring_add_event(req, -ECANCELED);
+               io_put_req(req);
+               return true;
+       }
+
+       return false;
+}
+
+static void io_fsync_finish(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       loff_t end = req->sync.off + req->sync.len;
+       struct io_kiocb *nxt = NULL;
        int ret;
 
-       fsync_flags = READ_ONCE(sqe->fsync_flags);
-       if (unlikely(fsync_flags & ~IORING_FSYNC_DATASYNC))
-               return -EINVAL;
+       if (io_req_cancelled(req))
+               return;
+
+       ret = vfs_fsync_range(req->rw.ki_filp, req->sync.off,
+                               end > 0 ? end : LLONG_MAX,
+                               req->sync.flags & IORING_FSYNC_DATASYNC);
+       if (ret < 0)
+               req_set_fail_links(req);
+       io_cqring_add_event(req, ret);
+       io_put_req_find_next(req, &nxt);
+       if (nxt)
+               *workptr = &nxt->work;
+}
+
+static int io_fsync(struct io_kiocb *req, struct io_kiocb **nxt,
+                   bool force_nonblock)
+{
+       struct io_wq_work *work, *old_work;
+       int ret;
 
-       ret = io_prep_fsync(req, sqe);
+       ret = io_prep_fsync(req);
        if (ret)
                return ret;
 
        /* fsync always requires a blocking context */
-       if (force_nonblock)
+       if (force_nonblock) {
+               io_put_req(req);
+               req->work.func = io_fsync_finish;
                return -EAGAIN;
+       }
 
-       ret = vfs_fsync_range(req->rw.ki_filp, sqe_off,
-                               end > 0 ? end : LLONG_MAX,
-                               fsync_flags & IORING_FSYNC_DATASYNC);
-
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
-       io_cqring_add_event(req, ret);
-       io_put_req_find_next(req, nxt);
+       work = old_work = &req->work;
+       io_fsync_finish(&work);
+       if (work && work != old_work)
+               *nxt = container_of(work, struct io_kiocb, work);
        return 0;
 }
 
-static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_prep_sfr(struct io_kiocb *req)
 {
+       const struct io_uring_sqe *sqe = req->sqe;
        struct io_ring_ctx *ctx = req->ctx;
-       int ret = 0;
 
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
        if (!req->file)
                return -EBADF;
 
@@ -1976,39 +2086,68 @@ static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (unlikely(sqe->addr || sqe->ioprio || sqe->buf_index))
                return -EINVAL;
 
-       return ret;
+       req->sync.off = READ_ONCE(sqe->off);
+       req->sync.len = READ_ONCE(sqe->len);
+       req->sync.flags = READ_ONCE(sqe->sync_range_flags);
+       req->flags |= REQ_F_PREPPED;
+       return 0;
 }
 
-static int io_sync_file_range(struct io_kiocb *req,
-                             const struct io_uring_sqe *sqe,
-                             struct io_kiocb **nxt,
+static void io_sync_file_range_finish(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct io_kiocb *nxt = NULL;
+       int ret;
+
+       if (io_req_cancelled(req))
+               return;
+
+       ret = sync_file_range(req->rw.ki_filp, req->sync.off, req->sync.len,
+                               req->sync.flags);
+       if (ret < 0)
+               req_set_fail_links(req);
+       io_cqring_add_event(req, ret);
+       io_put_req_find_next(req, &nxt);
+       if (nxt)
+               *workptr = &nxt->work;
+}
+
+static int io_sync_file_range(struct io_kiocb *req, struct io_kiocb **nxt,
                              bool force_nonblock)
 {
-       loff_t sqe_off;
-       loff_t sqe_len;
-       unsigned flags;
+       struct io_wq_work *work, *old_work;
        int ret;
 
-       ret = io_prep_sfr(req, sqe);
+       ret = io_prep_sfr(req);
        if (ret)
                return ret;
 
        /* sync_file_range always requires a blocking context */
-       if (force_nonblock)
+       if (force_nonblock) {
+               io_put_req(req);
+               req->work.func = io_sync_file_range_finish;
                return -EAGAIN;
+       }
 
-       sqe_off = READ_ONCE(sqe->off);
-       sqe_len = READ_ONCE(sqe->len);
-       flags = READ_ONCE(sqe->sync_range_flags);
+       work = old_work = &req->work;
+       io_sync_file_range_finish(&work);
+       if (work && work != old_work)
+               *nxt = container_of(work, struct io_kiocb, work);
+       return 0;
+}
 
-       ret = sync_file_range(req->rw.ki_filp, sqe_off, sqe_len, flags);
+#if defined(CONFIG_NET)
+static void io_sendrecv_async(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct iovec *iov = NULL;
 
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
-       io_cqring_add_event(req, ret);
-       io_put_req_find_next(req, nxt);
-       return 0;
+       if (req->io->rw.iov != req->io->rw.fast_iov)
+               iov = req->io->msg.iov;
+       io_wq_submit_work(workptr);
+       kfree(iov);
 }
+#endif
 
 static int io_sendmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
 {
@@ -2019,16 +2158,19 @@ static int io_sendmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
 
        flags = READ_ONCE(sqe->msg_flags);
        msg = (struct user_msghdr __user *)(unsigned long) READ_ONCE(sqe->addr);
+       io->msg.iov = io->msg.fast_iov;
        return sendmsg_copy_msghdr(&io->msg.msg, msg, flags, &io->msg.iov);
 #else
        return 0;
 #endif
 }
 
-static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
+       const struct io_uring_sqe *sqe = req->sqe;
+       struct io_async_msghdr *kmsg = NULL;
        struct socket *sock;
        int ret;
 
@@ -2037,9 +2179,8 @@ static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
        sock = sock_from_file(req->file, &ret);
        if (sock) {
-               struct io_async_ctx io, *copy;
+               struct io_async_ctx io;
                struct sockaddr_storage addr;
-               struct msghdr *kmsg;
                unsigned flags;
 
                flags = READ_ONCE(sqe->msg_flags);
@@ -2049,38 +2190,40 @@ static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                        flags |= MSG_DONTWAIT;
 
                if (req->io) {
-                       kmsg = &req->io->msg.msg;
-                       kmsg->msg_name = &addr;
+                       kmsg = &req->io->msg;
+                       kmsg->msg.msg_name = &addr;
+                       /* if iov is set, it's allocated already */
+                       if (!kmsg->iov)
+                               kmsg->iov = kmsg->fast_iov;
+                       kmsg->msg.msg_iter.iov = kmsg->iov;
                } else {
-                       kmsg = &io.msg.msg;
-                       kmsg->msg_name = &addr;
-                       io.msg.iov = io.msg.fast_iov;
+                       kmsg = &io.msg;
+                       kmsg->msg.msg_name = &addr;
                        ret = io_sendmsg_prep(req, &io);
                        if (ret)
                                goto out;
                }
 
-               ret = __sys_sendmsg_sock(sock, kmsg, flags);
+               ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags);
                if (force_nonblock && ret == -EAGAIN) {
-                       copy = kmalloc(sizeof(*copy), GFP_KERNEL);
-                       if (!copy) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       memcpy(&copy->msg, &io.msg, sizeof(copy->msg));
-                       req->io = copy;
-                       memcpy(&req->io->sqe, req->sqe, sizeof(*req->sqe));
-                       req->sqe = &req->io->sqe;
-                       return ret;
+                       if (req->io)
+                               return -EAGAIN;
+                       if (io_alloc_async_ctx(req))
+                               return -ENOMEM;
+                       memcpy(&req->io->msg, &io.msg, sizeof(io.msg));
+                       req->work.func = io_sendrecv_async;
+                       return -EAGAIN;
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
        }
 
 out:
+       if (!io_wq_current_is_worker() && kmsg && kmsg->iov != kmsg->fast_iov)
+               kfree(kmsg->iov);
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
        return 0;
 #else
@@ -2097,6 +2240,7 @@ static int io_recvmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
 
        flags = READ_ONCE(sqe->msg_flags);
        msg = (struct user_msghdr __user *)(unsigned long) READ_ONCE(sqe->addr);
+       io->msg.iov = io->msg.fast_iov;
        return recvmsg_copy_msghdr(&io->msg.msg, msg, flags, &io->msg.uaddr,
                                        &io->msg.iov);
 #else
@@ -2104,10 +2248,12 @@ static int io_recvmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
 #endif
 }
 
-static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
+       const struct io_uring_sqe *sqe = req->sqe;
+       struct io_async_msghdr *kmsg = NULL;
        struct socket *sock;
        int ret;
 
@@ -2117,9 +2263,8 @@ static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        sock = sock_from_file(req->file, &ret);
        if (sock) {
                struct user_msghdr __user *msg;
-               struct io_async_ctx io, *copy;
+               struct io_async_ctx io;
                struct sockaddr_storage addr;
-               struct msghdr *kmsg;
                unsigned flags;
 
                flags = READ_ONCE(sqe->msg_flags);
@@ -2131,38 +2276,40 @@ static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                msg = (struct user_msghdr __user *) (unsigned long)
                        READ_ONCE(sqe->addr);
                if (req->io) {
-                       kmsg = &req->io->msg.msg;
-                       kmsg->msg_name = &addr;
+                       kmsg = &req->io->msg;
+                       kmsg->msg.msg_name = &addr;
+                       /* if iov is set, it's allocated already */
+                       if (!kmsg->iov)
+                               kmsg->iov = kmsg->fast_iov;
+                       kmsg->msg.msg_iter.iov = kmsg->iov;
                } else {
-                       kmsg = &io.msg.msg;
-                       kmsg->msg_name = &addr;
-                       io.msg.iov = io.msg.fast_iov;
+                       kmsg = &io.msg;
+                       kmsg->msg.msg_name = &addr;
                        ret = io_recvmsg_prep(req, &io);
                        if (ret)
                                goto out;
                }
 
-               ret = __sys_recvmsg_sock(sock, kmsg, msg, io.msg.uaddr, flags);
+               ret = __sys_recvmsg_sock(sock, &kmsg->msg, msg, kmsg->uaddr, flags);
                if (force_nonblock && ret == -EAGAIN) {
-                       copy = kmalloc(sizeof(*copy), GFP_KERNEL);
-                       if (!copy) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       memcpy(copy, &io, sizeof(*copy));
-                       req->io = copy;
-                       memcpy(&req->io->sqe, req->sqe, sizeof(*req->sqe));
-                       req->sqe = &req->io->sqe;
-                       return ret;
+                       if (req->io)
+                               return -EAGAIN;
+                       if (io_alloc_async_ctx(req))
+                               return -ENOMEM;
+                       memcpy(&req->io->msg, &io.msg, sizeof(io.msg));
+                       req->work.func = io_sendrecv_async;
+                       return -EAGAIN;
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
        }
 
 out:
+       if (!io_wq_current_is_worker() && kmsg && kmsg->iov != kmsg->fast_iov)
+               kfree(kmsg->iov);
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
        return 0;
 #else
@@ -2170,37 +2317,84 @@ out:
 #endif
 }
 
-static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                    struct io_kiocb **nxt, bool force_nonblock)
+static int io_accept_prep(struct io_kiocb *req)
 {
 #if defined(CONFIG_NET)
-       struct sockaddr __user *addr;
-       int __user *addr_len;
-       unsigned file_flags;
-       int flags, ret;
+       const struct io_uring_sqe *sqe = req->sqe;
+       struct io_accept *accept = &req->accept;
+
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
 
        if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
                return -EINVAL;
        if (sqe->ioprio || sqe->len || sqe->buf_index)
                return -EINVAL;
 
-       addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
-       addr_len = (int __user *) (unsigned long) READ_ONCE(sqe->addr2);
-       flags = READ_ONCE(sqe->accept_flags);
-       file_flags = force_nonblock ? O_NONBLOCK : 0;
+       accept->addr = (struct sockaddr __user *)
+                               (unsigned long) READ_ONCE(sqe->addr);
+       accept->addr_len = (int __user *) (unsigned long) READ_ONCE(sqe->addr2);
+       accept->flags = READ_ONCE(sqe->accept_flags);
+       req->flags |= REQ_F_PREPPED;
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
+}
 
-       ret = __sys_accept4_file(req->file, file_flags, addr, addr_len, flags);
-       if (ret == -EAGAIN && force_nonblock) {
-               req->work.flags |= IO_WQ_WORK_NEEDS_FILES;
+#if defined(CONFIG_NET)
+static int __io_accept(struct io_kiocb *req, struct io_kiocb **nxt,
+                      bool force_nonblock)
+{
+       struct io_accept *accept = &req->accept;
+       unsigned file_flags;
+       int ret;
+
+       file_flags = force_nonblock ? O_NONBLOCK : 0;
+       ret = __sys_accept4_file(req->file, file_flags, accept->addr,
+                                       accept->addr_len, accept->flags);
+       if (ret == -EAGAIN && force_nonblock)
                return -EAGAIN;
-       }
        if (ret == -ERESTARTSYS)
                ret = -EINTR;
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_cqring_add_event(req, ret);
        io_put_req_find_next(req, nxt);
        return 0;
+}
+
+static void io_accept_finish(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct io_kiocb *nxt = NULL;
+
+       if (io_req_cancelled(req))
+               return;
+       __io_accept(req, &nxt, false);
+       if (nxt)
+               *workptr = &nxt->work;
+}
+#endif
+
+static int io_accept(struct io_kiocb *req, struct io_kiocb **nxt,
+                    bool force_nonblock)
+{
+#if defined(CONFIG_NET)
+       int ret;
+
+       ret = io_accept_prep(req);
+       if (ret)
+               return ret;
+
+       ret = __io_accept(req, nxt, force_nonblock);
+       if (ret == -EAGAIN && force_nonblock) {
+               req->work.func = io_accept_finish;
+               req->work.flags |= IO_WQ_WORK_NEEDS_FILES;
+               io_put_req(req);
+               return -EAGAIN;
+       }
+       return 0;
 #else
        return -EOPNOTSUPP;
 #endif
@@ -2221,10 +2415,11 @@ static int io_connect_prep(struct io_kiocb *req, struct io_async_ctx *io)
 #endif
 }
 
-static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_connect(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
+       const struct io_uring_sqe *sqe = req->sqe;
        struct io_async_ctx __io, *io;
        unsigned file_flags;
        int addr_len, ret;
@@ -2249,22 +2444,20 @@ static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        ret = __sys_connect_file(req->file, &io->connect.address, addr_len,
                                        file_flags);
        if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io) {
+               if (req->io)
+                       return -EAGAIN;
+               if (io_alloc_async_ctx(req)) {
                        ret = -ENOMEM;
                        goto out;
                }
-               memcpy(&io->connect, &__io.connect, sizeof(io->connect));
-               req->io = io;
-               memcpy(&io->sqe, req->sqe, sizeof(*req->sqe));
-               req->sqe = &io->sqe;
+               memcpy(&req->io->connect, &__io.connect, sizeof(__io.connect));
                return -EAGAIN;
        }
        if (ret == -ERESTARTSYS)
                ret = -EINTR;
 out:
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_cqring_add_event(req, ret);
        io_put_req_find_next(req, nxt);
        return 0;
@@ -2279,8 +2472,8 @@ static void io_poll_remove_one(struct io_kiocb *req)
 
        spin_lock(&poll->head->lock);
        WRITE_ONCE(poll->canceled, true);
-       if (!list_empty(&poll->wait->entry)) {
-               list_del_init(&poll->wait->entry);
+       if (!list_empty(&poll->wait.entry)) {
+               list_del_init(&poll->wait.entry);
                io_queue_async_work(req);
        }
        spin_unlock(&poll->head->lock);
@@ -2320,28 +2513,45 @@ static int io_poll_cancel(struct io_ring_ctx *ctx, __u64 sqe_addr)
        return -ENOENT;
 }
 
+static int io_poll_remove_prep(struct io_kiocb *req)
+{
+       const struct io_uring_sqe *sqe = req->sqe;
+
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index ||
+           sqe->poll_events)
+               return -EINVAL;
+
+       req->poll.addr = READ_ONCE(sqe->addr);
+       req->flags |= REQ_F_PREPPED;
+       return 0;
+}
+
 /*
  * Find a running poll command that matches one specified in sqe->addr,
  * and remove it if found.
  */
-static int io_poll_remove(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_poll_remove(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
+       u64 addr;
        int ret;
 
-       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
-               return -EINVAL;
-       if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index ||
-           sqe->poll_events)
-               return -EINVAL;
+       ret = io_poll_remove_prep(req);
+       if (ret)
+               return ret;
 
+       addr = req->poll.addr;
        spin_lock_irq(&ctx->completion_lock);
-       ret = io_poll_cancel(ctx, READ_ONCE(sqe->addr));
+       ret = io_poll_cancel(ctx, addr);
        spin_unlock_irq(&ctx->completion_lock);
 
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req(req);
        return 0;
 }
@@ -2351,7 +2561,6 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error)
        struct io_ring_ctx *ctx = req->ctx;
 
        req->poll.done = true;
-       kfree(req->poll.wait);
        if (error)
                io_cqring_fill_event(req, error);
        else
@@ -2389,7 +2598,7 @@ static void io_poll_complete_work(struct io_wq_work **workptr)
         */
        spin_lock_irq(&ctx->completion_lock);
        if (!mask && ret != -ECANCELED) {
-               add_wait_queue(poll->head, poll->wait);
+               add_wait_queue(poll->head, &poll->wait);
                spin_unlock_irq(&ctx->completion_lock);
                return;
        }
@@ -2399,8 +2608,8 @@ static void io_poll_complete_work(struct io_wq_work **workptr)
 
        io_cqring_ev_posted(ctx);
 
-       if (ret < 0 && req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, &nxt);
        if (nxt)
                *workptr = &nxt->work;
@@ -2419,7 +2628,7 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
        if (mask && !(mask & poll->events))
                return 0;
 
-       list_del_init(&poll->wait->entry);
+       list_del_init(&poll->wait.entry);
 
        /*
         * Run completion inline if we can. We're using trylock here because
@@ -2460,7 +2669,7 @@ static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
 
        pt->error = 0;
        pt->req->poll.head = head;
-       add_wait_queue(head, pt->req->poll.wait);
+       add_wait_queue(head, &pt->req->poll.wait);
 }
 
 static void io_poll_req_insert(struct io_kiocb *req)
@@ -2472,16 +2681,14 @@ static void io_poll_req_insert(struct io_kiocb *req)
        hlist_add_head(&req->hash_node, list);
 }
 
-static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                      struct io_kiocb **nxt)
+static int io_poll_add_prep(struct io_kiocb *req)
 {
+       const struct io_uring_sqe *sqe = req->sqe;
        struct io_poll_iocb *poll = &req->poll;
-       struct io_ring_ctx *ctx = req->ctx;
-       struct io_poll_table ipt;
-       bool cancel = false;
-       __poll_t mask;
        u16 events;
 
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
        if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
        if (sqe->addr || sqe->ioprio || sqe->off || sqe->len || sqe->buf_index)
@@ -2489,14 +2696,26 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        if (!poll->file)
                return -EBADF;
 
-       poll->wait = kmalloc(sizeof(*poll->wait), GFP_KERNEL);
-       if (!poll->wait)
-               return -ENOMEM;
-
-       req->io = NULL;
-       INIT_IO_WORK(&req->work, io_poll_complete_work);
+       req->flags |= REQ_F_PREPPED;
        events = READ_ONCE(sqe->poll_events);
        poll->events = demangle_poll(events) | EPOLLERR | EPOLLHUP;
+       return 0;
+}
+
+static int io_poll_add(struct io_kiocb *req, struct io_kiocb **nxt)
+{
+       struct io_poll_iocb *poll = &req->poll;
+       struct io_ring_ctx *ctx = req->ctx;
+       struct io_poll_table ipt;
+       bool cancel = false;
+       __poll_t mask;
+       int ret;
+
+       ret = io_poll_add_prep(req);
+       if (ret)
+               return ret;
+
+       INIT_IO_WORK(&req->work, io_poll_complete_work);
        INIT_HLIST_NODE(&req->hash_node);
 
        poll->head = NULL;
@@ -2509,9 +2728,9 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        ipt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */
 
        /* initialized the list so that we can do list_empty checks */
-       INIT_LIST_HEAD(&poll->wait->entry);
-       init_waitqueue_func_entry(poll->wait, io_poll_wake);
-       poll->wait->private = poll;
+       INIT_LIST_HEAD(&poll->wait.entry);
+       init_waitqueue_func_entry(&poll->wait, io_poll_wake);
+       poll->wait.private = poll;
 
        INIT_LIST_HEAD(&req->list);
 
@@ -2520,14 +2739,14 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        spin_lock_irq(&ctx->completion_lock);
        if (likely(poll->head)) {
                spin_lock(&poll->head->lock);
-               if (unlikely(list_empty(&poll->wait->entry))) {
+               if (unlikely(list_empty(&poll->wait.entry))) {
                        if (ipt.error)
                                cancel = true;
                        ipt.error = 0;
                        mask = 0;
                }
                if (mask || ipt.error)
-                       list_del_init(&poll->wait->entry);
+                       list_del_init(&poll->wait.entry);
                else if (cancel)
                        WRITE_ONCE(poll->canceled, true);
                else if (!poll->done) /* actually waiting for an event */
@@ -2567,7 +2786,7 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
 
                /*
                 * Adjust the reqs sequence before the current one because it
-                * will consume a slot in the cq_ring and the the cq_tail
+                * will consume a slot in the cq_ring and the cq_tail
                 * pointer will be increased, otherwise other timeout reqs may
                 * return in advance without waiting for enough wait_nr.
                 */
@@ -2582,8 +2801,7 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
        io_cqring_ev_posted(ctx);
-       if (req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       req_set_fail_links(req);
        io_put_req(req);
        return HRTIMER_NORESTART;
 }
@@ -2608,40 +2826,53 @@ static int io_timeout_cancel(struct io_ring_ctx *ctx, __u64 user_data)
        if (ret == -1)
                return -EALREADY;
 
-       if (req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       req_set_fail_links(req);
        io_cqring_fill_event(req, -ECANCELED);
        io_put_req(req);
        return 0;
 }
 
+static int io_timeout_remove_prep(struct io_kiocb *req)
+{
+       const struct io_uring_sqe *sqe = req->sqe;
+
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+               return -EINVAL;
+       if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len)
+               return -EINVAL;
+
+       req->timeout.addr = READ_ONCE(sqe->addr);
+       req->timeout.flags = READ_ONCE(sqe->timeout_flags);
+       if (req->timeout.flags)
+               return -EINVAL;
+
+       req->flags |= REQ_F_PREPPED;
+       return 0;
+}
+
 /*
  * Remove or update an existing timeout command
  */
-static int io_timeout_remove(struct io_kiocb *req,
-                            const struct io_uring_sqe *sqe)
+static int io_timeout_remove(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       unsigned flags;
        int ret;
 
-       if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
-               return -EINVAL;
-       if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len)
-               return -EINVAL;
-       flags = READ_ONCE(sqe->timeout_flags);
-       if (flags)
-               return -EINVAL;
+       ret = io_timeout_remove_prep(req);
+       if (ret)
+               return ret;
 
        spin_lock_irq(&ctx->completion_lock);
-       ret = io_timeout_cancel(ctx, READ_ONCE(sqe->addr));
+       ret = io_timeout_cancel(ctx, req->timeout.addr);
 
        io_cqring_fill_event(req, ret);
        io_commit_cqring(ctx);
        spin_unlock_irq(&ctx->completion_lock);
        io_cqring_ev_posted(ctx);
-       if (ret < 0 && req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req(req);
        return 0;
 }
@@ -2676,31 +2907,25 @@ static int io_timeout_prep(struct io_kiocb *req, struct io_async_ctx *io,
                data->mode = HRTIMER_MODE_REL;
 
        hrtimer_init(&data->timer, CLOCK_MONOTONIC, data->mode);
-       req->io = io;
        return 0;
 }
 
-static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_timeout(struct io_kiocb *req)
 {
+       const struct io_uring_sqe *sqe = req->sqe;
        unsigned count;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_timeout_data *data;
-       struct io_async_ctx *io;
        struct list_head *entry;
        unsigned span = 0;
+       int ret;
 
-       io = req->io;
-       if (!io) {
-               int ret;
-
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io)
+       if (!req->io) {
+               if (io_alloc_async_ctx(req))
                        return -ENOMEM;
-               ret = io_timeout_prep(req, io, false);
-               if (ret) {
-                       kfree(io);
+               ret = io_timeout_prep(req, req->io, false);
+               if (ret)
                        return ret;
-               }
        }
        data = &req->io->timeout;
 
@@ -2822,43 +3047,84 @@ done:
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
        io_cqring_ev_posted(ctx);
 
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
 }
 
-static int io_async_cancel(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                          struct io_kiocb **nxt)
+static int io_async_cancel_prep(struct io_kiocb *req)
 {
-       struct io_ring_ctx *ctx = req->ctx;
+       const struct io_uring_sqe *sqe = req->sqe;
 
-       if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
+       if (req->flags & REQ_F_PREPPED)
+               return 0;
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
        if (sqe->flags || sqe->ioprio || sqe->off || sqe->len ||
            sqe->cancel_flags)
                return -EINVAL;
 
-       io_async_find_and_cancel(ctx, req, READ_ONCE(sqe->addr), nxt, 0);
+       req->flags |= REQ_F_PREPPED;
+       req->cancel.addr = READ_ONCE(sqe->addr);
+       return 0;
+}
+
+static int io_async_cancel(struct io_kiocb *req, struct io_kiocb **nxt)
+{
+       struct io_ring_ctx *ctx = req->ctx;
+       int ret;
+
+       ret = io_async_cancel_prep(req);
+       if (ret)
+               return ret;
+
+       io_async_find_and_cancel(ctx, req, req->cancel.addr, nxt, 0);
        return 0;
 }
 
-static int io_req_defer_prep(struct io_kiocb *req, struct io_async_ctx *io)
+static int io_req_defer_prep(struct io_kiocb *req)
 {
        struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
+       struct io_async_ctx *io = req->io;
        struct iov_iter iter;
-       ssize_t ret;
-
-       memcpy(&io->sqe, req->sqe, sizeof(io->sqe));
-       req->sqe = &io->sqe;
+       ssize_t ret = 0;
 
-       switch (io->sqe.opcode) {
+       switch (req->opcode) {
+       case IORING_OP_NOP:
+               break;
        case IORING_OP_READV:
        case IORING_OP_READ_FIXED:
+               /* ensure prep does right import */
+               req->io = NULL;
                ret = io_read_prep(req, &iovec, &iter, true);
+               req->io = io;
+               if (ret < 0)
+                       break;
+               io_req_map_rw(req, ret, iovec, inline_vecs, &iter);
+               ret = 0;
                break;
        case IORING_OP_WRITEV:
        case IORING_OP_WRITE_FIXED:
+               /* ensure prep does right import */
+               req->io = NULL;
                ret = io_write_prep(req, &iovec, &iter, true);
+               req->io = io;
+               if (ret < 0)
+                       break;
+               io_req_map_rw(req, ret, iovec, inline_vecs, &iter);
+               ret = 0;
+               break;
+       case IORING_OP_POLL_ADD:
+               ret = io_poll_add_prep(req);
+               break;
+       case IORING_OP_POLL_REMOVE:
+               ret = io_poll_remove_prep(req);
+               break;
+       case IORING_OP_FSYNC:
+               ret = io_prep_fsync(req);
+               break;
+       case IORING_OP_SYNC_FILE_RANGE:
+               ret = io_prep_sfr(req);
                break;
        case IORING_OP_SENDMSG:
                ret = io_sendmsg_prep(req, io);
@@ -2870,41 +3136,45 @@ static int io_req_defer_prep(struct io_kiocb *req, struct io_async_ctx *io)
                ret = io_connect_prep(req, io);
                break;
        case IORING_OP_TIMEOUT:
-               return io_timeout_prep(req, io, false);
+               ret = io_timeout_prep(req, io, false);
+               break;
+       case IORING_OP_TIMEOUT_REMOVE:
+               ret = io_timeout_remove_prep(req);
+               break;
+       case IORING_OP_ASYNC_CANCEL:
+               ret = io_async_cancel_prep(req);
+               break;
        case IORING_OP_LINK_TIMEOUT:
-               return io_timeout_prep(req, io, true);
+               ret = io_timeout_prep(req, io, true);
+               break;
+       case IORING_OP_ACCEPT:
+               ret = io_accept_prep(req);
+               break;
        default:
-               req->io = io;
-               return 0;
+               printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n",
+                               req->opcode);
+               ret = -EINVAL;
+               break;
        }
 
-       if (ret < 0)
-               return ret;
-
-       req->io = io;
-       io_req_map_io(req, ret, iovec, inline_vecs, &iter);
-       return 0;
+       return ret;
 }
 
 static int io_req_defer(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       struct io_async_ctx *io;
        int ret;
 
        /* Still need defer if there is pending req in defer list. */
        if (!req_need_defer(req) && list_empty(&ctx->defer_list))
                return 0;
 
-       io = kmalloc(sizeof(*io), GFP_KERNEL);
-       if (!io)
+       if (io_alloc_async_ctx(req))
                return -EAGAIN;
 
-       ret = io_req_defer_prep(req, io);
-       if (ret < 0) {
-               kfree(io);
+       ret = io_req_defer_prep(req);
+       if (ret < 0)
                return ret;
-       }
 
        spin_lock_irq(&ctx->completion_lock);
        if (!req_need_defer(req) && list_empty(&ctx->defer_list)) {
@@ -2922,11 +3192,10 @@ __attribute__((nonnull))
 static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
                        bool force_nonblock)
 {
-       int ret, opcode;
        struct io_ring_ctx *ctx = req->ctx;
+       int ret;
 
-       opcode = READ_ONCE(req->sqe->opcode);
-       switch (opcode) {
+       switch (req->opcode) {
        case IORING_OP_NOP:
                ret = io_nop(req);
                break;
@@ -2947,37 +3216,37 @@ static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
                ret = io_write(req, nxt, force_nonblock);
                break;
        case IORING_OP_FSYNC:
-               ret = io_fsync(req, req->sqe, nxt, force_nonblock);
+               ret = io_fsync(req, nxt, force_nonblock);
                break;
        case IORING_OP_POLL_ADD:
-               ret = io_poll_add(req, req->sqe, nxt);
+               ret = io_poll_add(req, nxt);
                break;
        case IORING_OP_POLL_REMOVE:
-               ret = io_poll_remove(req, req->sqe);
+               ret = io_poll_remove(req);
                break;
        case IORING_OP_SYNC_FILE_RANGE:
-               ret = io_sync_file_range(req, req->sqe, nxt, force_nonblock);
+               ret = io_sync_file_range(req, nxt, force_nonblock);
                break;
        case IORING_OP_SENDMSG:
-               ret = io_sendmsg(req, req->sqe, nxt, force_nonblock);
+               ret = io_sendmsg(req, nxt, force_nonblock);
                break;
        case IORING_OP_RECVMSG:
-               ret = io_recvmsg(req, req->sqe, nxt, force_nonblock);
+               ret = io_recvmsg(req, nxt, force_nonblock);
                break;
        case IORING_OP_TIMEOUT:
-               ret = io_timeout(req, req->sqe);
+               ret = io_timeout(req);
                break;
        case IORING_OP_TIMEOUT_REMOVE:
-               ret = io_timeout_remove(req, req->sqe);
+               ret = io_timeout_remove(req);
                break;
        case IORING_OP_ACCEPT:
-               ret = io_accept(req, req->sqe, nxt, force_nonblock);
+               ret = io_accept(req, nxt, force_nonblock);
                break;
        case IORING_OP_CONNECT:
-               ret = io_connect(req, req->sqe, nxt, force_nonblock);
+               ret = io_connect(req, nxt, force_nonblock);
                break;
        case IORING_OP_ASYNC_CANCEL:
-               ret = io_async_cancel(req, req->sqe, nxt);
+               ret = io_async_cancel(req, nxt);
                break;
        default:
                ret = -EINVAL;
@@ -2991,12 +3260,7 @@ static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
                if (req->result == -EAGAIN)
                        return -EAGAIN;
 
-               /* workqueue context doesn't hold uring_lock, grab it now */
-               if (req->in_async)
-                       mutex_lock(&ctx->uring_lock);
                io_iopoll_req_issued(req);
-               if (req->in_async)
-                       mutex_unlock(&ctx->uring_lock);
        }
 
        return 0;
@@ -3018,9 +3282,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        struct io_kiocb *nxt = NULL;
        int ret = 0;
 
-       /* Ensure we clear previously set non-block flag */
-       req->rw.ki_flags &= ~IOCB_NOWAIT;
-
        if (work->flags & IO_WQ_WORK_CANCEL)
                ret = -ECANCELED;
 
@@ -3044,8 +3305,7 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        io_put_req(req);
 
        if (ret) {
-               if (req->flags & REQ_F_LINK)
-                       req->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(req);
                io_cqring_add_event(req, ret);
                io_put_req(req);
        }
@@ -3064,20 +3324,25 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        }
 }
 
-static bool io_op_needs_file(const struct io_uring_sqe *sqe)
+static bool io_req_op_valid(int op)
 {
-       int op = READ_ONCE(sqe->opcode);
+       return op >= IORING_OP_NOP && op < IORING_OP_LAST;
+}
 
-       switch (op) {
+static int io_req_needs_file(struct io_kiocb *req)
+{
+       switch (req->opcode) {
        case IORING_OP_NOP:
        case IORING_OP_POLL_REMOVE:
        case IORING_OP_TIMEOUT:
        case IORING_OP_TIMEOUT_REMOVE:
        case IORING_OP_ASYNC_CANCEL:
        case IORING_OP_LINK_TIMEOUT:
-               return false;
+               return 0;
        default:
-               return true;
+               if (io_req_op_valid(req->opcode))
+                       return 1;
+               return -EINVAL;
        }
 }
 
@@ -3094,7 +3359,7 @@ static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
        unsigned flags;
-       int fd;
+       int fd, ret;
 
        flags = READ_ONCE(req->sqe->flags);
        fd = READ_ONCE(req->sqe->fd);
@@ -3102,8 +3367,9 @@ static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req)
        if (flags & IOSQE_IO_DRAIN)
                req->flags |= REQ_F_IO_DRAIN;
 
-       if (!io_op_needs_file(req->sqe))
-               return 0;
+       ret = io_req_needs_file(req);
+       if (ret <= 0)
+               return ret;
 
        if (flags & IOSQE_FIXED_FILE) {
                if (unlikely(!ctx->file_table ||
@@ -3179,8 +3445,7 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
        if (prev) {
-               if (prev->flags & REQ_F_LINK)
-                       prev->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(prev);
                io_async_find_and_cancel(ctx, req, prev->user_data, NULL,
                                                -ETIME);
                io_put_req(prev);
@@ -3222,7 +3487,7 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 
        nxt = list_first_entry_or_null(&req->link_list, struct io_kiocb,
                                        link_list);
-       if (!nxt || nxt->sqe->opcode != IORING_OP_LINK_TIMEOUT)
+       if (!nxt || nxt->opcode != IORING_OP_LINK_TIMEOUT)
                return NULL;
 
        req->flags |= REQ_F_LINK_TIMEOUT;
@@ -3231,13 +3496,14 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 
 static void __io_queue_sqe(struct io_kiocb *req)
 {
-       struct io_kiocb *linked_timeout = io_prep_linked_timeout(req);
+       struct io_kiocb *linked_timeout;
        struct io_kiocb *nxt = NULL;
        int ret;
 
+again:
+       linked_timeout = io_prep_linked_timeout(req);
+
        ret = io_issue_sqe(req, &nxt, true);
-       if (nxt)
-               io_queue_async_work(nxt);
 
        /*
         * We async punt it if the file wasn't marked NOWAIT, or if the file
@@ -3256,7 +3522,7 @@ static void __io_queue_sqe(struct io_kiocb *req)
                 * submit reference when the iocb is actually submitted.
                 */
                io_queue_async_work(req);
-               return;
+               goto done_req;
        }
 
 err:
@@ -3273,10 +3539,15 @@ err:
        /* and drop final reference, if we failed */
        if (ret) {
                io_cqring_add_event(req, ret);
-               if (req->flags & REQ_F_LINK)
-                       req->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(req);
                io_put_req(req);
        }
+done_req:
+       if (nxt) {
+               req = nxt;
+               nxt = NULL;
+               goto again;
+       }
 }
 
 static void io_queue_sqe(struct io_kiocb *req)
@@ -3293,8 +3564,7 @@ static void io_queue_sqe(struct io_kiocb *req)
        if (ret) {
                if (ret != -EIOCBQUEUED) {
                        io_cqring_add_event(req, ret);
-                       if (req->flags & REQ_F_LINK)
-                               req->flags |= REQ_F_FAIL_LINK;
+                       req_set_fail_links(req);
                        io_double_put_req(req);
                }
        } else
@@ -3310,8 +3580,8 @@ static inline void io_queue_link_head(struct io_kiocb *req)
                io_queue_sqe(req);
 }
 
-
-#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK)
+#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK| \
+                               IOSQE_IO_HARDLINK)
 
 static bool io_submit_sqe(struct io_kiocb *req, struct io_submit_state *state,
                          struct io_kiocb **link)
@@ -3319,8 +3589,6 @@ static bool io_submit_sqe(struct io_kiocb *req, struct io_submit_state *state,
        struct io_ring_ctx *ctx = req->ctx;
        int ret;
 
-       req->user_data = req->sqe->user_data;
-
        /* enforce forwards compatibility on users */
        if (unlikely(req->sqe->flags & ~SQE_VALID_FLAGS)) {
                ret = -EINVAL;
@@ -3344,27 +3612,30 @@ err_req:
         */
        if (*link) {
                struct io_kiocb *prev = *link;
-               struct io_async_ctx *io;
 
                if (req->sqe->flags & IOSQE_IO_DRAIN)
                        (*link)->flags |= REQ_F_DRAIN_LINK | REQ_F_IO_DRAIN;
 
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io) {
+               if (req->sqe->flags & IOSQE_IO_HARDLINK)
+                       req->flags |= REQ_F_HARDLINK;
+
+               if (io_alloc_async_ctx(req)) {
                        ret = -EAGAIN;
                        goto err_req;
                }
 
-               ret = io_req_defer_prep(req, io);
+               ret = io_req_defer_prep(req);
                if (ret) {
-                       kfree(io);
+                       /* fail even hard links since we don't submit */
                        prev->flags |= REQ_F_FAIL_LINK;
                        goto err_req;
                }
                trace_io_uring_link(ctx, req, prev);
                list_add_tail(&req->link_list, &prev->link_list);
-       } else if (req->sqe->flags & IOSQE_IO_LINK) {
+       } else if (req->sqe->flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) {
                req->flags |= REQ_F_LINK;
+               if (req->sqe->flags & IOSQE_IO_HARDLINK)
+                       req->flags |= REQ_F_HARDLINK;
 
                INIT_LIST_HEAD(&req->link_list);
                *link = req;
@@ -3414,7 +3685,7 @@ static void io_commit_sqring(struct io_ring_ctx *ctx)
 }
 
 /*
- * Fetch an sqe, if one is available. Note that s->sqe will point to memory
+ * Fetch an sqe, if one is available. Note that req->sqe will point to memory
  * that is mapped by userspace. This means that care needs to be taken to
  * ensure that reads are stable, as we cannot rely on userspace always
  * being a good citizen. If members of the sqe are validated and then later
@@ -3449,6 +3720,8 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req)
                 */
                req->sequence = ctx->cached_sq_head;
                req->sqe = &ctx->sq_sqes[head];
+               req->opcode = READ_ONCE(req->sqe->opcode);
+               req->user_data = READ_ONCE(req->sqe->user_data);
                ctx->cached_sq_head++;
                return true;
        }
@@ -3494,7 +3767,7 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                        break;
                }
 
-               if (io_sqe_needs_user(req->sqe) && !*mm) {
+               if (io_req_needs_user(req) && !*mm) {
                        mm_fault = mm_fault || !mmget_not_zero(ctx->sqo_mm);
                        if (!mm_fault) {
                                use_mm(ctx->sqo_mm);
@@ -3510,15 +3783,14 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                req->has_user = *mm != NULL;
                req->in_async = async;
                req->needs_fixed_file = async;
-               trace_io_uring_submit_sqe(ctx, req->sqe->user_data,
-                                         true, async);
+               trace_io_uring_submit_sqe(ctx, req->user_data, true, async);
                if (!io_submit_sqe(req, statep, &link))
                        break;
                /*
                 * If previous wasn't linked and we have a linked command,
                 * that's the end of the chain. Submit the previous link.
                 */
-               if (!(sqe_flags & IOSQE_IO_LINK) && link) {
+               if (!(sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) && link) {
                        io_queue_link_head(link);
                        link = NULL;
                }
@@ -3647,7 +3919,9 @@ static int io_sq_thread(void *data)
                }
 
                to_submit = min(to_submit, ctx->sq_entries);
+               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;
        }
@@ -3676,7 +3950,7 @@ static inline bool io_should_wake(struct io_wait_queue *iowq, bool noflush)
        struct io_ring_ctx *ctx = iowq->ctx;
 
        /*
-        * Wake up if we have enough events, or if a timeout occured since we
+        * Wake up if we have enough events, or if a timeout occurred since we
         * started waiting. For timeouts, we always want to return to userspace,
         * regardless of event count.
         */
@@ -4866,6 +5140,9 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                submitted = io_submit_sqes(ctx, to_submit, f.file, fd,
                                           &cur_mm, false);
                mutex_unlock(&ctx->uring_lock);
+
+               if (submitted != to_submit)
+                       goto out;
        }
        if (flags & IORING_ENTER_GETEVENTS) {
                unsigned nr_events = 0;
@@ -4879,6 +5156,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                }
        }
 
+out:
        percpu_ref_put(&ctx->refs);
 out_fput:
        fdput(f);
index 2fd0c8b..be601d3 100644 (file)
@@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name)
 }
 EXPORT_SYMBOL(mount_subtree);
 
-int ksys_mount(const char __user *dev_name, const char __user *dir_name,
-              const char __user *type, unsigned long flags, void __user *data)
+SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
+               char __user *, type, unsigned long, flags, void __user *, data)
 {
        int ret;
        char *kernel_type;
@@ -3359,12 +3359,6 @@ out_type:
        return ret;
 }
 
-SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
-               char __user *, type, unsigned long, flags, void __user *, data)
-{
-       return ksys_mount(dev_name, dir_name, type, flags, data);
-}
-
 /*
  * Create a kernel mount representation for a new, prepared superblock
  * (specified by fs_fd) and attach to an open_tree-like file descriptor.
index b801c63..6220642 100644 (file)
@@ -227,13 +227,17 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
 struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
 {
        struct ovl_fh *fh;
-       int fh_type, fh_len, dwords;
-       void *buf;
+       int fh_type, dwords;
        int buflen = MAX_HANDLE_SZ;
        uuid_t *uuid = &real->d_sb->s_uuid;
+       int err;
 
-       buf = kmalloc(buflen, GFP_KERNEL);
-       if (!buf)
+       /* Make sure the real fid stays 32bit aligned */
+       BUILD_BUG_ON(OVL_FH_FID_OFFSET % 4);
+       BUILD_BUG_ON(MAX_HANDLE_SZ + OVL_FH_FID_OFFSET > 255);
+
+       fh = kzalloc(buflen + OVL_FH_FID_OFFSET, GFP_KERNEL);
+       if (!fh)
                return ERR_PTR(-ENOMEM);
 
        /*
@@ -242,27 +246,19 @@ struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
         * the price or reconnecting the dentry.
         */
        dwords = buflen >> 2;
-       fh_type = exportfs_encode_fh(real, buf, &dwords, 0);
+       fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0);
        buflen = (dwords << 2);
 
-       fh = ERR_PTR(-EIO);
+       err = -EIO;
        if (WARN_ON(fh_type < 0) ||
            WARN_ON(buflen > MAX_HANDLE_SZ) ||
            WARN_ON(fh_type == FILEID_INVALID))
-               goto out;
+               goto out_err;
 
-       BUILD_BUG_ON(MAX_HANDLE_SZ + offsetof(struct ovl_fh, fid) > 255);
-       fh_len = offsetof(struct ovl_fh, fid) + buflen;
-       fh = kmalloc(fh_len, GFP_KERNEL);
-       if (!fh) {
-               fh = ERR_PTR(-ENOMEM);
-               goto out;
-       }
-
-       fh->version = OVL_FH_VERSION;
-       fh->magic = OVL_FH_MAGIC;
-       fh->type = fh_type;
-       fh->flags = OVL_FH_FLAG_CPU_ENDIAN;
+       fh->fb.version = OVL_FH_VERSION;
+       fh->fb.magic = OVL_FH_MAGIC;
+       fh->fb.type = fh_type;
+       fh->fb.flags = OVL_FH_FLAG_CPU_ENDIAN;
        /*
         * When we will want to decode an overlay dentry from this handle
         * and all layers are on the same fs, if we get a disconncted real
@@ -270,14 +266,15 @@ struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
         * it to upperdentry or to lowerstack is by checking this flag.
         */
        if (is_upper)
-               fh->flags |= OVL_FH_FLAG_PATH_UPPER;
-       fh->len = fh_len;
-       fh->uuid = *uuid;
-       memcpy(fh->fid, buf, buflen);
+               fh->fb.flags |= OVL_FH_FLAG_PATH_UPPER;
+       fh->fb.len = sizeof(fh->fb) + buflen;
+       fh->fb.uuid = *uuid;
 
-out:
-       kfree(buf);
        return fh;
+
+out_err:
+       kfree(fh);
+       return ERR_PTR(err);
 }
 
 int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
@@ -300,8 +297,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
        /*
         * Do not fail when upper doesn't support xattrs.
         */
-       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh,
-                                fh ? fh->len : 0, 0);
+       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh->buf,
+                                fh ? fh->fb.len : 0, 0);
        kfree(fh);
 
        return err;
@@ -317,7 +314,7 @@ static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index)
        if (IS_ERR(fh))
                return PTR_ERR(fh);
 
-       err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh, fh->len, 0);
+       err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh->buf, fh->fb.len, 0);
 
        kfree(fh);
        return err;
index 702aa63..29abdb1 100644 (file)
@@ -1170,7 +1170,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
        if (newdentry == trap)
                goto out_dput;
 
-       if (WARN_ON(olddentry->d_inode == newdentry->d_inode))
+       if (olddentry->d_inode == newdentry->d_inode)
                goto out_dput;
 
        err = 0;
index 73c9775..70e5558 100644 (file)
@@ -211,10 +211,11 @@ static int ovl_check_encode_origin(struct dentry *dentry)
        return 1;
 }
 
-static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
+static int ovl_dentry_to_fid(struct dentry *dentry, u32 *fid, int buflen)
 {
        struct ovl_fh *fh = NULL;
        int err, enc_lower;
+       int len;
 
        /*
         * Check if we should encode a lower or upper file handle and maybe
@@ -231,11 +232,12 @@ static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
                return PTR_ERR(fh);
 
        err = -EOVERFLOW;
-       if (fh->len > buflen)
+       len = OVL_FH_LEN(fh);
+       if (len > buflen)
                goto fail;
 
-       memcpy(buf, (char *)fh, fh->len);
-       err = fh->len;
+       memcpy(fid, fh, len);
+       err = len;
 
 out:
        kfree(fh);
@@ -243,31 +245,16 @@ out:
 
 fail:
        pr_warn_ratelimited("overlayfs: failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n",
-                           dentry, err, buflen, fh ? (int)fh->len : 0,
-                           fh ? fh->type : 0);
+                           dentry, err, buflen, fh ? (int)fh->fb.len : 0,
+                           fh ? fh->fb.type : 0);
        goto out;
 }
 
-static int ovl_dentry_to_fh(struct dentry *dentry, u32 *fid, int *max_len)
-{
-       int res, len = *max_len << 2;
-
-       res = ovl_d_to_fh(dentry, (char *)fid, len);
-       if (res <= 0)
-               return FILEID_INVALID;
-
-       len = res;
-
-       /* Round up to dwords */
-       *max_len = (len + 3) >> 2;
-       return OVL_FILEID;
-}
-
 static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
                         struct inode *parent)
 {
        struct dentry *dentry;
-       int type;
+       int bytes = *max_len << 2;
 
        /* TODO: encode connectable file handles */
        if (parent)
@@ -277,10 +264,14 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
        if (WARN_ON(!dentry))
                return FILEID_INVALID;
 
-       type = ovl_dentry_to_fh(dentry, fid, max_len);
-
+       bytes = ovl_dentry_to_fid(dentry, fid, bytes);
        dput(dentry);
-       return type;
+       if (bytes <= 0)
+               return FILEID_INVALID;
+
+       *max_len = bytes >> 2;
+
+       return OVL_FILEID_V1;
 }
 
 /*
@@ -777,24 +768,45 @@ out_err:
        goto out;
 }
 
+static struct ovl_fh *ovl_fid_to_fh(struct fid *fid, int buflen, int fh_type)
+{
+       struct ovl_fh *fh;
+
+       /* If on-wire inner fid is aligned - nothing to do */
+       if (fh_type == OVL_FILEID_V1)
+               return (struct ovl_fh *)fid;
+
+       if (fh_type != OVL_FILEID_V0)
+               return ERR_PTR(-EINVAL);
+
+       fh = kzalloc(buflen, GFP_KERNEL);
+       if (!fh)
+               return ERR_PTR(-ENOMEM);
+
+       /* Copy unaligned inner fh into aligned buffer */
+       memcpy(&fh->fb, fid, buflen - OVL_FH_WIRE_OFFSET);
+       return fh;
+}
+
 static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
                                       int fh_len, int fh_type)
 {
        struct dentry *dentry = NULL;
-       struct ovl_fh *fh = (struct ovl_fh *) fid;
+       struct ovl_fh *fh = NULL;
        int len = fh_len << 2;
        unsigned int flags = 0;
        int err;
 
-       err = -EINVAL;
-       if (fh_type != OVL_FILEID)
+       fh = ovl_fid_to_fh(fid, len, fh_type);
+       err = PTR_ERR(fh);
+       if (IS_ERR(fh))
                goto out_err;
 
        err = ovl_check_fh_len(fh, len);
        if (err)
                goto out_err;
 
-       flags = fh->flags;
+       flags = fh->fb.flags;
        dentry = (flags & OVL_FH_FLAG_PATH_UPPER) ?
                 ovl_upper_fh_to_d(sb, fh) :
                 ovl_lower_fh_to_d(sb, fh);
@@ -802,12 +814,18 @@ static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
        if (IS_ERR(dentry) && err != -ESTALE)
                goto out_err;
 
+out:
+       /* We may have needed to re-align OVL_FILEID_V0 */
+       if (!IS_ERR_OR_NULL(fh) && fh != (void *)fid)
+               kfree(fh);
+
        return dentry;
 
 out_err:
        pr_warn_ratelimited("overlayfs: failed to decode file handle (len=%d, type=%d, flags=%x, err=%i)\n",
-                           len, fh_type, flags, err);
-       return ERR_PTR(err);
+                           fh_len, fh_type, flags, err);
+       dentry = ERR_PTR(err);
+       goto out;
 }
 
 static struct dentry *ovl_fh_to_parent(struct super_block *sb, struct fid *fid,
index bc14781..b045cf1 100644 (file)
@@ -200,8 +200,14 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
                        if (ovl_test_flag(OVL_INDEX, d_inode(dentry)) ||
                            (!ovl_verify_lower(dentry->d_sb) &&
                             (is_dir || lowerstat.nlink == 1))) {
-                               stat->ino = lowerstat.ino;
                                lower_layer = ovl_layer_lower(dentry);
+                               /*
+                                * Cannot use origin st_dev;st_ino because
+                                * origin inode content may differ from overlay
+                                * inode content.
+                                */
+                               if (samefs || lower_layer->fsid)
+                                       stat->ino = lowerstat.ino;
                        }
 
                        /*
index c269d60..76ff663 100644 (file)
@@ -84,21 +84,21 @@ static int ovl_acceptable(void *ctx, struct dentry *dentry)
  * Return -ENODATA for "origin unknown".
  * Return <0 for an invalid file handle.
  */
-int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
+int ovl_check_fb_len(struct ovl_fb *fb, int fb_len)
 {
-       if (fh_len < sizeof(struct ovl_fh) || fh_len < fh->len)
+       if (fb_len < sizeof(struct ovl_fb) || fb_len < fb->len)
                return -EINVAL;
 
-       if (fh->magic != OVL_FH_MAGIC)
+       if (fb->magic != OVL_FH_MAGIC)
                return -EINVAL;
 
        /* Treat larger version and unknown flags as "origin unknown" */
-       if (fh->version > OVL_FH_VERSION || fh->flags & ~OVL_FH_FLAG_ALL)
+       if (fb->version > OVL_FH_VERSION || fb->flags & ~OVL_FH_FLAG_ALL)
                return -ENODATA;
 
        /* Treat endianness mismatch as "origin unknown" */
-       if (!(fh->flags & OVL_FH_FLAG_ANY_ENDIAN) &&
-           (fh->flags & OVL_FH_FLAG_BIG_ENDIAN) != OVL_FH_FLAG_CPU_ENDIAN)
+       if (!(fb->flags & OVL_FH_FLAG_ANY_ENDIAN) &&
+           (fb->flags & OVL_FH_FLAG_BIG_ENDIAN) != OVL_FH_FLAG_CPU_ENDIAN)
                return -ENODATA;
 
        return 0;
@@ -119,15 +119,15 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
        if (res == 0)
                return NULL;
 
-       fh = kzalloc(res, GFP_KERNEL);
+       fh = kzalloc(res + OVL_FH_WIRE_OFFSET, GFP_KERNEL);
        if (!fh)
                return ERR_PTR(-ENOMEM);
 
-       res = vfs_getxattr(dentry, name, fh, res);
+       res = vfs_getxattr(dentry, name, fh->buf, res);
        if (res < 0)
                goto fail;
 
-       err = ovl_check_fh_len(fh, res);
+       err = ovl_check_fb_len(&fh->fb, res);
        if (err < 0) {
                if (err == -ENODATA)
                        goto out;
@@ -158,12 +158,12 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
         * Make sure that the stored uuid matches the uuid of the lower
         * layer where file handle will be decoded.
         */
-       if (!uuid_equal(&fh->uuid, &mnt->mnt_sb->s_uuid))
+       if (!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid))
                return NULL;
 
-       bytes = (fh->len - offsetof(struct ovl_fh, fid));
-       real = exportfs_decode_fh(mnt, (struct fid *)fh->fid,
-                                 bytes >> 2, (int)fh->type,
+       bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));
+       real = exportfs_decode_fh(mnt, (struct fid *)fh->fb.fid,
+                                 bytes >> 2, (int)fh->fb.type,
                                  connected ? ovl_acceptable : NULL, mnt);
        if (IS_ERR(real)) {
                /*
@@ -173,7 +173,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
                 * index entries correctly.
                 */
                if (real == ERR_PTR(-ESTALE) &&
-                   !(fh->flags & OVL_FH_FLAG_PATH_UPPER))
+                   !(fh->fb.flags & OVL_FH_FLAG_PATH_UPPER))
                        real = NULL;
                return real;
        }
@@ -323,6 +323,14 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
        int i;
 
        for (i = 0; i < ofs->numlower; i++) {
+               /*
+                * If lower fs uuid is not unique among lower fs we cannot match
+                * fh->uuid to layer.
+                */
+               if (ofs->lower_layers[i].fsid &&
+                   ofs->lower_layers[i].fs->bad_uuid)
+                       continue;
+
                origin = ovl_decode_real_fh(fh, ofs->lower_layers[i].mnt,
                                            connected);
                if (origin)
@@ -400,7 +408,7 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name,
        if (IS_ERR(ofh))
                return PTR_ERR(ofh);
 
-       if (fh->len != ofh->len || memcmp(fh, ofh, fh->len))
+       if (fh->fb.len != ofh->fb.len || memcmp(&fh->fb, &ofh->fb, fh->fb.len))
                err = -ESTALE;
 
        kfree(ofh);
@@ -431,7 +439,7 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name,
 
        err = ovl_verify_fh(dentry, name, fh);
        if (set && err == -ENODATA)
-               err = ovl_do_setxattr(dentry, name, fh, fh->len, 0);
+               err = ovl_do_setxattr(dentry, name, fh->buf, fh->fb.len, 0);
        if (err)
                goto fail;
 
@@ -505,20 +513,20 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
                goto fail;
 
        err = -EINVAL;
-       if (index->d_name.len < sizeof(struct ovl_fh)*2)
+       if (index->d_name.len < sizeof(struct ovl_fb)*2)
                goto fail;
 
        err = -ENOMEM;
        len = index->d_name.len / 2;
-       fh = kzalloc(len, GFP_KERNEL);
+       fh = kzalloc(len + OVL_FH_WIRE_OFFSET, GFP_KERNEL);
        if (!fh)
                goto fail;
 
        err = -EINVAL;
-       if (hex2bin((u8 *)fh, index->d_name.name, len))
+       if (hex2bin(fh->buf, index->d_name.name, len))
                goto fail;
 
-       err = ovl_check_fh_len(fh, len);
+       err = ovl_check_fb_len(&fh->fb, len);
        if (err)
                goto fail;
 
@@ -597,11 +605,11 @@ static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name)
 {
        char *n, *s;
 
-       n = kcalloc(fh->len, 2, GFP_KERNEL);
+       n = kcalloc(fh->fb.len, 2, GFP_KERNEL);
        if (!n)
                return -ENOMEM;
 
-       s  = bin2hex(n, fh, fh->len);
+       s  = bin2hex(n, fh->buf, fh->fb.len);
        *name = (struct qstr) QSTR_INIT(n, s - n);
 
        return 0;
index 6934bcf..f283b1d 100644 (file)
@@ -71,20 +71,36 @@ enum ovl_entry_flag {
 #error Endianness not defined
 #endif
 
-/* The type returned by overlay exportfs ops when encoding an ovl_fh handle */
-#define OVL_FILEID     0xfb
+/* The type used to be returned by overlay exportfs for misaligned fid */
+#define OVL_FILEID_V0  0xfb
+/* The type returned by overlay exportfs for 32bit aligned fid */
+#define OVL_FILEID_V1  0xf8
 
-/* On-disk and in-memeory format for redirect by file handle */
-struct ovl_fh {
+/* On-disk format for "origin" file handle */
+struct ovl_fb {
        u8 version;     /* 0 */
        u8 magic;       /* 0xfb */
        u8 len;         /* size of this header + size of fid */
        u8 flags;       /* OVL_FH_FLAG_* */
        u8 type;        /* fid_type of fid */
        uuid_t uuid;    /* uuid of filesystem */
-       u8 fid[0];      /* file identifier */
+       u32 fid[0];     /* file identifier should be 32bit aligned in-memory */
 } __packed;
 
+/* In-memory and on-wire format for overlay file handle */
+struct ovl_fh {
+       u8 padding[3];  /* make sure fb.fid is 32bit aligned */
+       union {
+               struct ovl_fb fb;
+               u8 buf[0];
+       };
+} __packed;
+
+#define OVL_FH_WIRE_OFFSET     offsetof(struct ovl_fh, fb)
+#define OVL_FH_LEN(fh)         (OVL_FH_WIRE_OFFSET + (fh)->fb.len)
+#define OVL_FH_FID_OFFSET      (OVL_FH_WIRE_OFFSET + \
+                                offsetof(struct ovl_fb, fid))
+
 static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
 {
        int err = vfs_rmdir(dir, dentry);
@@ -302,7 +318,13 @@ static inline void ovl_inode_unlock(struct inode *inode)
 
 
 /* namei.c */
-int ovl_check_fh_len(struct ovl_fh *fh, int fh_len);
+int ovl_check_fb_len(struct ovl_fb *fb, int fb_len);
+
+static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
+{
+       return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
+}
+
 struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
                                  bool connected);
 int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
index a827928..28348c4 100644 (file)
@@ -22,6 +22,8 @@ struct ovl_config {
 struct ovl_sb {
        struct super_block *sb;
        dev_t pseudo_dev;
+       /* Unusable (conflicting) uuid */
+       bool bad_uuid;
 };
 
 struct ovl_layer {
index afbcb11..7621ff1 100644 (file)
@@ -1255,7 +1255,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
 {
        unsigned int i;
 
-       if (!ofs->config.nfs_export && !(ofs->config.index && ofs->upper_mnt))
+       if (!ofs->config.nfs_export && !ofs->upper_mnt)
                return true;
 
        for (i = 0; i < ofs->numlowerfs; i++) {
@@ -1263,9 +1263,13 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
                 * We use uuid to associate an overlay lower file handle with a
                 * lower layer, so we can accept lower fs with null uuid as long
                 * as all lower layers with null uuid are on the same fs.
+                * if we detect multiple lower fs with the same uuid, we
+                * disable lower file handle decoding on all of them.
                 */
-               if (uuid_equal(&ofs->lower_fs[i].sb->s_uuid, uuid))
+               if (uuid_equal(&ofs->lower_fs[i].sb->s_uuid, uuid)) {
+                       ofs->lower_fs[i].bad_uuid = true;
                        return false;
+               }
        }
        return true;
 }
@@ -1277,6 +1281,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
        unsigned int i;
        dev_t dev;
        int err;
+       bool bad_uuid = false;
 
        /* fsid 0 is reserved for upper fs even with non upper overlay */
        if (ofs->upper_mnt && ofs->upper_mnt->mnt_sb == sb)
@@ -1288,11 +1293,15 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
        }
 
        if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
-               ofs->config.index = false;
-               ofs->config.nfs_export = false;
-               pr_warn("overlayfs: %s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n",
-                       uuid_is_null(&sb->s_uuid) ? "null" : "conflicting",
-                       path->dentry);
+               bad_uuid = true;
+               if (ofs->config.index || ofs->config.nfs_export) {
+                       ofs->config.index = false;
+                       ofs->config.nfs_export = false;
+                       pr_warn("overlayfs: %s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n",
+                               uuid_is_null(&sb->s_uuid) ? "null" :
+                                                           "conflicting",
+                               path->dentry);
+               }
        }
 
        err = get_anon_bdev(&dev);
@@ -1303,6 +1312,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
 
        ofs->lower_fs[ofs->numlowerfs].sb = sb;
        ofs->lower_fs[ofs->numlowerfs].pseudo_dev = dev;
+       ofs->lower_fs[ofs->numlowerfs].bad_uuid = bad_uuid;
        ofs->numlowerfs++;
 
        return ofs->numlowerfs;
index 87109e7..04d004e 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -364,17 +364,39 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                        ret = -EAGAIN;
                        break;
                }
-               if (signal_pending(current)) {
-                       if (!ret)
-                               ret = -ERESTARTSYS;
-                       break;
-               }
                __pipe_unlock(pipe);
-               if (was_full) {
+
+               /*
+                * We only get here if we didn't actually read anything.
+                *
+                * However, we could have seen (and removed) a zero-sized
+                * pipe buffer, and might have made space in the buffers
+                * that way.
+                *
+                * You can't make zero-sized pipe buffers by doing an empty
+                * write (not even in packet mode), but they can happen if
+                * the writer gets an EFAULT when trying to fill a buffer
+                * that already got allocated and inserted in the buffer
+                * array.
+                *
+                * So we still need to wake up any pending writers in the
+                * _very_ unlikely case that the pipe was full, but we got
+                * no data.
+                */
+               if (unlikely(was_full)) {
                        wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
                        kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
                }
-               wait_event_interruptible(pipe->wait, pipe_readable(pipe));
+
+               /*
+                * But because we didn't read anything, at this point we can
+                * just return directly with -ERESTARTSYS if we're interrupted,
+                * since we've done any required wakeups and there's no need
+                * to mark anything accessed. And we've dropped the lock.
+                */
+               if (wait_event_interruptible(pipe->wait, pipe_readable(pipe)) < 0)
+                       return -ERESTARTSYS;
+
                __pipe_lock(pipe);
                was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
        }
index 37bdbec..fd931d3 100644 (file)
@@ -134,7 +134,7 @@ static int show_stat(struct seq_file *p, void *v)
                softirq         += cpustat[CPUTIME_SOFTIRQ];
                steal           += cpustat[CPUTIME_STEAL];
                guest           += cpustat[CPUTIME_GUEST];
-               guest_nice      += cpustat[CPUTIME_USER];
+               guest_nice      += cpustat[CPUTIME_GUEST_NICE];
                sum             += kstat_cpu_irqs_sum(i);
                sum             += arch_irq_stat_cpu(i);
 
@@ -175,7 +175,7 @@ static int show_stat(struct seq_file *p, void *v)
                softirq         = cpustat[CPUTIME_SOFTIRQ];
                steal           = cpustat[CPUTIME_STEAL];
                guest           = cpustat[CPUTIME_GUEST];
-               guest_nice      = cpustat[CPUTIME_USER];
+               guest_nice      = cpustat[CPUTIME_GUEST_NICE];
                seq_printf(p, "cpu%d", i);
                seq_put_decimal_ull(p, " ", nsec_to_clock_t(user));
                seq_put_decimal_ull(p, " ", nsec_to_clock_t(nice));
index eabc6ac..b79e3fd 100644 (file)
@@ -315,7 +315,7 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
        if (arg.block_size != PAGE_SIZE)
                return -EINVAL;
 
-       if (arg.salt_size > FIELD_SIZEOF(struct fsverity_descriptor, salt))
+       if (arg.salt_size > sizeof_field(struct fsverity_descriptor, salt))
                return -EMSGSIZE;
 
        if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE)
index 19394c7..e4a6949 100644 (file)
@@ -188,7 +188,6 @@ struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg,
 struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
                                    struct request_queue *q);
 int blkcg_init_queue(struct request_queue *q);
-void blkcg_drain_queue(struct request_queue *q);
 void blkcg_exit_queue(struct request_queue *q);
 
 /* Blkio controller policy registration */
@@ -720,7 +719,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { ret
 static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
 { return NULL; }
 static inline int blkcg_init_queue(struct request_queue *q) { return 0; }
-static inline void blkcg_drain_queue(struct request_queue *q) { }
 static inline void blkcg_exit_queue(struct request_queue *q) { }
 static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
 static inline void blkcg_policy_unregister(struct blkcg_policy *pol) { }
index 92d5fdc..31b1b0e 100644 (file)
@@ -595,17 +595,6 @@ struct governor_attr {
                         size_t count);
 };
 
-static inline bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
-{
-       /*
-        * Allow remote callbacks if:
-        * - dvfs_possible_from_any_cpu flag is set
-        * - the local and remote CPUs share cpufreq policy
-        */
-       return policy->dvfs_possible_from_any_cpu ||
-               cpumask_test_cpu(smp_processor_id(), policy->cpus);
-}
-
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
index 2bae9ed..fb376b5 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
 
 #define DEVFREQ_NAME_LEN 16
 
@@ -123,8 +124,8 @@ struct devfreq_dev_profile {
  * @previous_freq:     previously configured frequency value.
  * @data:      Private data of the governor. The devfreq framework does not
  *             touch this.
- * @min_freq:  Limit minimum frequency requested by user (0: none)
- * @max_freq:  Limit maximum frequency requested by user (0: none)
+ * @user_min_freq_req: PM QoS minimum frequency request from user (via sysfs)
+ * @user_max_freq_req: PM QoS maximum frequency request from user (via sysfs)
  * @scaling_min_freq:  Limit minimum frequency requested by OPP interface
  * @scaling_max_freq:  Limit maximum frequency requested by OPP interface
  * @stop_polling:       devfreq polling status of a device.
@@ -136,6 +137,8 @@ struct devfreq_dev_profile {
  * @time_in_state:     Statistics of devfreq states
  * @last_stat_updated: The last time stat updated
  * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
+ * @nb_min:            Notifier block for DEV_PM_QOS_MIN_FREQUENCY
+ * @nb_max:            Notifier block for DEV_PM_QOS_MAX_FREQUENCY
  *
  * This structure stores the devfreq information for a give device.
  *
@@ -161,8 +164,8 @@ struct devfreq {
 
        void *data; /* private data for governors */
 
-       unsigned long min_freq;
-       unsigned long max_freq;
+       struct dev_pm_qos_request user_min_freq_req;
+       struct dev_pm_qos_request user_max_freq_req;
        unsigned long scaling_min_freq;
        unsigned long scaling_max_freq;
        bool stop_polling;
@@ -178,6 +181,9 @@ struct devfreq {
        unsigned long last_stat_updated;
 
        struct srcu_notifier_head transition_notifier_list;
+
+       struct notifier_block nb_min;
+       struct notifier_block nb_max;
 };
 
 struct devfreq_freqs {
index e226030..96ff767 100644 (file)
@@ -1666,11 +1666,11 @@ extern bool kill_device(struct device *dev);
 #ifdef CONFIG_DEVTMPFS
 extern int devtmpfs_create_node(struct device *dev);
 extern int devtmpfs_delete_node(struct device *dev);
-extern int devtmpfs_mount(const char *mntdir);
+extern int devtmpfs_mount(void);
 #else
 static inline int devtmpfs_create_node(struct device *dev) { return 0; }
 static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
-static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
+static inline int devtmpfs_mount(void) { return 0; }
 #endif
 
 /* drivers/base/power/shutdown.c */
index 99dfea5..aa54586 100644 (file)
@@ -824,7 +824,7 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       u32 unload;
 } efi_loaded_image_32_t;
 
 typedef struct {
@@ -840,14 +840,14 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       u64 unload;
 } efi_loaded_image_64_t;
 
 typedef struct {
        u32 revision;
-       void *parent_handle;
+       efi_handle_t parent_handle;
        efi_system_table_t *system_table;
-       void *device_handle;
+       efi_handle_t device_handle;
        void *file_path;
        void *reserved;
        u32 load_options_size;
@@ -856,7 +856,7 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       efi_status_t (*unload)(efi_handle_t image_handle);
 } efi_loaded_image_t;
 
 
index a141cb0..345f374 100644 (file)
@@ -420,7 +420,7 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 
 #define BPF_FIELD_SIZEOF(type, field)                          \
        ({                                                      \
-               const int __size = bytes_to_bpf_size(FIELD_SIZEOF(type, field)); \
+               const int __size = bytes_to_bpf_size(sizeof_field(type, field)); \
                BUILD_BUG_ON(__size < 0);                       \
                __size;                                         \
        })
@@ -497,7 +497,7 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 
 #define bpf_target_off(TYPE, MEMBER, SIZE, PTR_SIZE)                           \
        ({                                                                      \
-               BUILD_BUG_ON(FIELD_SIZEOF(TYPE, MEMBER) != (SIZE));             \
+               BUILD_BUG_ON(sizeof_field(TYPE, MEMBER) != (SIZE));             \
                *(PTR_SIZE) = (SIZE);                                           \
                offsetof(TYPE, MEMBER);                                         \
        })
@@ -608,7 +608,7 @@ static inline void bpf_compute_data_pointers(struct sk_buff *skb)
 {
        struct bpf_skb_data_end *cb = (struct bpf_skb_data_end *)skb->cb;
 
-       BUILD_BUG_ON(sizeof(*cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb));
        cb->data_meta = skb->data - skb_metadata_len(skb);
        cb->data_end  = skb->data + skb_headlen(skb);
 }
@@ -646,9 +646,9 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
         * attached to sockets, we need to clear the bpf_skb_cb() area
         * to not leak previous contents to user space.
         */
-       BUILD_BUG_ON(FIELD_SIZEOF(struct __sk_buff, cb) != BPF_SKB_CB_LEN);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct __sk_buff, cb) !=
-                    FIELD_SIZEOF(struct qdisc_skb_cb, data));
+       BUILD_BUG_ON(sizeof_field(struct __sk_buff, cb) != BPF_SKB_CB_LEN);
+       BUILD_BUG_ON(sizeof_field(struct __sk_buff, cb) !=
+                    sizeof_field(struct qdisc_skb_cb, data));
 
        return qdisc_skb_cb(skb)->data;
 }
index 7247d35..db95244 100644 (file)
@@ -264,6 +264,7 @@ int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
                                struct dyn_ftrace *rec,
                                unsigned long old_addr,
                                unsigned long new_addr);
+unsigned long ftrace_find_rec_direct(unsigned long ip);
 #else
 # define ftrace_direct_func_count 0
 static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
@@ -290,6 +291,10 @@ static inline int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
 {
        return -ENODEV;
 }
+static inline unsigned long ftrace_find_rec_direct(unsigned long ip)
+{
+       return 0;
+}
 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
 
 #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
index d2f7867..582ef05 100644 (file)
@@ -300,6 +300,7 @@ struct i2c_driver {
  *     generic enough to hide second-sourcing and compatible revisions.
  * @adapter: manages the bus segment hosting this I2C device
  * @dev: Driver model device node for the slave.
+ * @init_irq: IRQ that was set at initialization
  * @irq: indicates the IRQ generated by this device (if any)
  * @detected: member of an i2c_driver.clients list or i2c-core's
  *     userspace_devices list
@@ -466,12 +467,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 /* Common custom probe functions */
 extern int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
 
-/* For devices that use several addresses, use i2c_new_dummy() to make
- * client handles for the extra addresses.
- */
-extern struct i2c_client *
-i2c_new_dummy(struct i2c_adapter *adap, u16 address);
-
 extern struct i2c_client *
 i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address);
 
@@ -856,6 +851,11 @@ extern void i2c_del_driver(struct i2c_driver *driver);
 #define i2c_add_driver(driver) \
        i2c_register_driver(THIS_MODULE, driver)
 
+static inline bool i2c_client_has_driver(struct i2c_client *client)
+{
+       return !IS_ERR_OR_NULL(client) && client->dev.driver;
+}
+
 /* call the i2c_client->command() of all attached clients with
  * the given arguments */
 extern void i2c_clients_command(struct i2c_adapter *adap,
index d77fe34..aa59143 100644 (file)
@@ -28,3 +28,5 @@ extern unsigned int real_root_dev;
 
 extern char __initramfs_start[];
 extern unsigned long __initramfs_size;
+
+void console_on_rootfs(void);
index 4f404c5..e18fe54 100644 (file)
@@ -205,20 +205,23 @@ static inline void *kasan_reset_tag(const void *addr)
 #endif /* CONFIG_KASAN_SW_TAGS */
 
 #ifdef CONFIG_KASAN_VMALLOC
-int kasan_populate_vmalloc(unsigned long requested_size,
-                          struct vm_struct *area);
-void kasan_poison_vmalloc(void *start, unsigned long size);
+int kasan_populate_vmalloc(unsigned long addr, unsigned long size);
+void kasan_poison_vmalloc(const void *start, unsigned long size);
+void kasan_unpoison_vmalloc(const void *start, unsigned long size);
 void kasan_release_vmalloc(unsigned long start, unsigned long end,
                           unsigned long free_region_start,
                           unsigned long free_region_end);
 #else
-static inline int kasan_populate_vmalloc(unsigned long requested_size,
-                                        struct vm_struct *area)
+static inline int kasan_populate_vmalloc(unsigned long start,
+                                       unsigned long size)
 {
        return 0;
 }
 
-static inline void kasan_poison_vmalloc(void *start, unsigned long size) {}
+static inline void kasan_poison_vmalloc(const void *start, unsigned long size)
+{ }
+static inline void kasan_unpoison_vmalloc(const void *start, unsigned long size)
+{ }
 static inline void kasan_release_vmalloc(unsigned long start,
                                         unsigned long end,
                                         unsigned long free_region_start,
index 7ed1e2f..538c25e 100644 (file)
@@ -149,7 +149,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQUEST_ARCH_BASE     8
 
 #define KVM_ARCH_REQ_FLAGS(nr, flags) ({ \
-       BUILD_BUG_ON((unsigned)(nr) >= (FIELD_SIZEOF(struct kvm_vcpu, requests) * 8) - KVM_REQUEST_ARCH_BASE); \
+       BUILD_BUG_ON((unsigned)(nr) >= (sizeof_field(struct kvm_vcpu, requests) * 8) - KVM_REQUEST_ARCH_BASE); \
        (unsigned)(((nr) + KVM_REQUEST_ARCH_BASE) | (flags)); \
 })
 #define KVM_ARCH_REQ(nr)           KVM_ARCH_REQ_FLAGS(nr, 0)
index c97ea3b..80a9162 100644 (file)
@@ -2621,6 +2621,9 @@ static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags)
 typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data);
 extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
                               unsigned long size, pte_fn_t fn, void *data);
+extern int apply_to_existing_page_range(struct mm_struct *mm,
+                                  unsigned long address, unsigned long size,
+                                  pte_fn_t fn, void *data);
 
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
index 10f8162..6d0d70f 100644 (file)
@@ -270,6 +270,8 @@ struct nvme_fc_remote_port {
  *
  * Host/Initiator Transport Entrypoints/Parameters:
  *
+ * @module:  The LLDD module using the interface
+ *
  * @localport_delete:  The LLDD initiates deletion of a localport via
  *       nvme_fc_deregister_localport(). However, the teardown is
  *       asynchronous. This routine is called upon the completion of the
@@ -383,6 +385,8 @@ struct nvme_fc_remote_port {
  *       Value is Mandatory. Allowed to be zero.
  */
 struct nvme_fc_port_template {
+       struct module   *module;
+
        /* initiator-based functions */
        void    (*localport_delete)(struct nvme_fc_local_port *);
        void    (*remoteport_delete)(struct nvme_fc_remote_port *);
index 3d507a8..5c4d7a7 100644 (file)
@@ -14,7 +14,7 @@ struct phy_device;
 #define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE      11
 
 #define PHY_LINK_LED_TRIGGER_NAME_SIZE (MII_BUS_ID_SIZE + \
-                                      FIELD_SIZEOF(struct mdio_device, addr)+\
+                                      sizeof_field(struct mdio_device, addr)+\
                                       PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE)
 
 struct phy_led_trigger {
index 0b93804..8cfe570 100644 (file)
@@ -49,6 +49,7 @@ struct sysc_regbits {
        s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_FORCE_MSTANDBY      BIT(20)
 #define SYSC_MODULE_QUIRK_AESS         BIT(19)
 #define SYSC_MODULE_QUIRK_SGX          BIT(18)
 #define SYSC_MODULE_QUIRK_HDQ1W                BIT(17)
index c09d67e..1e6108b 100644 (file)
@@ -302,9 +302,8 @@ extern int kptr_restrict;
        printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_err(fmt, ...) \
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning(fmt, ...) \
+#define pr_warn(fmt, ...) \
        printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn pr_warning
 #define pr_notice(fmt, ...) \
        printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_info(fmt, ...) \
index afa940c..cc6bcc1 100644 (file)
@@ -12,6 +12,8 @@
 #define SCHED_CPUFREQ_MIGRATION        (1U << 1)
 
 #ifdef CONFIG_CPU_FREQ
+struct cpufreq_policy;
+
 struct update_util_data {
        void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
 };
@@ -20,6 +22,7 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
                        void (*func)(struct update_util_data *data, u64 time,
                                    unsigned int flags));
 void cpufreq_remove_update_util_hook(int cpu);
+bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);
 
 static inline unsigned long map_util_freq(unsigned long util,
                                        unsigned long freq, unsigned long cap)
index d0391cc..2960ded 100644 (file)
@@ -1231,10 +1231,7 @@ asmlinkage long sys_ni_syscall(void);
  * the ksys_xyzyyz() functions prototyped below.
  */
 
-int ksys_mount(const char __user *dev_name, const char __user *dir_name,
-              const char __user *type, unsigned long flags, void __user *data);
 int ksys_umount(char __user *name, int flags);
-int ksys_dup(unsigned int fildes);
 int ksys_chroot(const char __user *filename);
 ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
 int ksys_chdir(const char __user *filename);
index 0d6e949..03e9b18 100644 (file)
@@ -403,6 +403,7 @@ extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
 extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
 extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
 extern struct tpm_chip *tpm_default_chip(void);
+void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
 #else
 static inline int tpm_is_tpm2(struct tpm_chip *chip)
 {
index c41833b..4d9a0c6 100644 (file)
@@ -37,7 +37,7 @@ struct garp_skb_cb {
 static inline struct garp_skb_cb *garp_cb(struct sk_buff *skb)
 {
        BUILD_BUG_ON(sizeof(struct garp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        return (struct garp_skb_cb *)skb->cb;
 }
 
index af64560..236503a 100644 (file)
@@ -33,8 +33,8 @@
 /* Used to memset ipv4 address padding. */
 #define IP_TUNNEL_KEY_IPV4_PAD offsetofend(struct ip_tunnel_key, u.ipv4.dst)
 #define IP_TUNNEL_KEY_IPV4_PAD_LEN                             \
-       (FIELD_SIZEOF(struct ip_tunnel_key, u) -                \
-        FIELD_SIZEOF(struct ip_tunnel_key, u.ipv4))
+       (sizeof_field(struct ip_tunnel_key, u) -                \
+        sizeof_field(struct ip_tunnel_key, u.ipv4))
 
 struct ip_tunnel_key {
        __be64                  tun_id;
@@ -63,7 +63,7 @@ struct ip_tunnel_key {
 
 /* Maximum tunnel options length. */
 #define IP_TUNNEL_OPTS_MAX                                     \
-       GENMASK((FIELD_SIZEOF(struct ip_tunnel_info,            \
+       GENMASK((sizeof_field(struct ip_tunnel_info,            \
                              options_len) * BITS_PER_BYTE) - 1, 0)
 
 struct ip_tunnel_info {
index ef58b4a..1c308c0 100644 (file)
@@ -39,7 +39,7 @@ struct mrp_skb_cb {
 static inline struct mrp_skb_cb *mrp_cb(struct sk_buff *skb)
 {
        BUILD_BUG_ON(sizeof(struct mrp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        return (struct mrp_skb_cb *)skb->cb;
 }
 
index 44b5a00..37f0fbe 100644 (file)
@@ -81,7 +81,7 @@ struct nf_conn_help {
 };
 
 #define NF_CT_HELPER_BUILD_BUG_ON(structsize) \
-       BUILD_BUG_ON((structsize) > FIELD_SIZEOF(struct nf_conn_help, data))
+       BUILD_BUG_ON((structsize) > sizeof_field(struct nf_conn_help, data))
 
 struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
                                                       u16 l3num, u8 protonum);
index 7281895..2656155 100644 (file)
@@ -41,7 +41,7 @@ struct nft_immediate_expr {
  */
 static inline u32 nft_cmp_fast_mask(unsigned int len)
 {
-       return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
+       return cpu_to_le32(~0U >> (sizeof_field(struct nft_cmp_fast_expr,
                                                data) * BITS_PER_BYTE - len));
 }
 
index 87d54ef..80f9964 100644 (file)
@@ -2305,7 +2305,7 @@ struct sock_skb_cb {
  * using skb->cb[] would keep using it directly and utilize its
  * alignement guarantee.
  */
-#define SOCK_SKB_CB_OFFSET ((FIELD_SIZEOF(struct sk_buff, cb) - \
+#define SOCK_SKB_CB_OFFSET ((sizeof_field(struct sk_buff, cb) - \
                            sizeof(struct sock_skb_cb)))
 
 #define SOCK_SKB_CB(__skb) ((struct sock_skb_cb *)((__skb)->cb + \
index cacb48f..5608e14 100644 (file)
@@ -2832,6 +2832,11 @@ int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
 int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
                                struct rdma_user_mmap_entry *entry,
                                size_t length);
+int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext,
+                                     struct rdma_user_mmap_entry *entry,
+                                     size_t length, u32 min_pgoff,
+                                     u32 max_pgoff);
+
 struct rdma_user_mmap_entry *
 rdma_user_mmap_entry_get_pgoff(struct ib_ucontext *ucontext,
                               unsigned long pgoff);
index c28a1ed..2628967 100644 (file)
@@ -1150,6 +1150,7 @@ struct snd_soc_pcm_runtime {
        unsigned int num_codecs;
 
        struct delayed_work delayed_work;
+       void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd);
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_dpcm_root;
 #endif
index eabccb4..a3300e1 100644 (file)
@@ -48,6 +48,7 @@ struct io_uring_sqe {
 #define IOSQE_FIXED_FILE       (1U << 0)       /* use fixed fileset */
 #define IOSQE_IO_DRAIN         (1U << 1)       /* issue after inflight IO */
 #define IOSQE_IO_LINK          (1U << 2)       /* links next sqe */
+#define IOSQE_IO_HARDLINK      (1U << 3)       /* like LINK, but stronger */
 
 /*
  * io_uring_setup() flags
@@ -57,23 +58,28 @@ struct io_uring_sqe {
 #define IORING_SETUP_SQ_AFF    (1U << 2)       /* sq_thread_cpu is valid */
 #define IORING_SETUP_CQSIZE    (1U << 3)       /* app defines CQ size */
 
-#define IORING_OP_NOP          0
-#define IORING_OP_READV                1
-#define IORING_OP_WRITEV       2
-#define IORING_OP_FSYNC                3
-#define IORING_OP_READ_FIXED   4
-#define IORING_OP_WRITE_FIXED  5
-#define IORING_OP_POLL_ADD     6
-#define IORING_OP_POLL_REMOVE  7
-#define IORING_OP_SYNC_FILE_RANGE      8
-#define IORING_OP_SENDMSG      9
-#define IORING_OP_RECVMSG      10
-#define IORING_OP_TIMEOUT      11
-#define IORING_OP_TIMEOUT_REMOVE       12
-#define IORING_OP_ACCEPT       13
-#define IORING_OP_ASYNC_CANCEL 14
-#define IORING_OP_LINK_TIMEOUT 15
-#define IORING_OP_CONNECT      16
+enum {
+       IORING_OP_NOP,
+       IORING_OP_READV,
+       IORING_OP_WRITEV,
+       IORING_OP_FSYNC,
+       IORING_OP_READ_FIXED,
+       IORING_OP_WRITE_FIXED,
+       IORING_OP_POLL_ADD,
+       IORING_OP_POLL_REMOVE,
+       IORING_OP_SYNC_FILE_RANGE,
+       IORING_OP_SENDMSG,
+       IORING_OP_RECVMSG,
+       IORING_OP_TIMEOUT,
+       IORING_OP_TIMEOUT_REMOVE,
+       IORING_OP_ACCEPT,
+       IORING_OP_ASYNC_CANCEL,
+       IORING_OP_LINK_TIMEOUT,
+       IORING_OP_CONNECT,
+
+       /* this goes last, obviously */
+       IORING_OP_LAST,
+};
 
 /*
  * sqe->fsync_flags
index 3f40501..2af7a1c 100644 (file)
@@ -125,35 +125,24 @@ struct __name##_back_ring {                                               \
     memset((_s)->pad, 0, sizeof((_s)->pad));                           \
 } while(0)
 
-#define FRONT_RING_INIT(_r, _s, __size) do {                           \
-    (_r)->req_prod_pvt = 0;                                            \
-    (_r)->rsp_cons = 0;                                                        \
+#define FRONT_RING_ATTACH(_r, _s, _i, __size) do {                     \
+    (_r)->req_prod_pvt = (_i);                                         \
+    (_r)->rsp_cons = (_i);                                             \
     (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
     (_r)->sring = (_s);                                                        \
 } while (0)
 
-#define BACK_RING_INIT(_r, _s, __size) do {                            \
-    (_r)->rsp_prod_pvt = 0;                                            \
-    (_r)->req_cons = 0;                                                        \
-    (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
-    (_r)->sring = (_s);                                                        \
-} while (0)
+#define FRONT_RING_INIT(_r, _s, __size) FRONT_RING_ATTACH(_r, _s, 0, __size)
 
-/* Initialize to existing shared indexes -- for recovery */
-#define FRONT_RING_ATTACH(_r, _s, __size) do {                         \
-    (_r)->sring = (_s);                                                        \
-    (_r)->req_prod_pvt = (_s)->req_prod;                               \
-    (_r)->rsp_cons = (_s)->rsp_prod;                                   \
+#define BACK_RING_ATTACH(_r, _s, _i, __size) do {                      \
+    (_r)->rsp_prod_pvt = (_i);                                         \
+    (_r)->req_cons = (_i);                                             \
     (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
-} while (0)
-
-#define BACK_RING_ATTACH(_r, _s, __size) do {                          \
     (_r)->sring = (_s);                                                        \
-    (_r)->rsp_prod_pvt = (_s)->rsp_prod;                               \
-    (_r)->req_cons = (_s)->req_prod;                                   \
-    (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
 } while (0)
 
+#define BACK_RING_INIT(_r, _s, __size) BACK_RING_ATTACH(_r, _s, 0, __size)
+
 /* How big is this ring? */
 #define RING_SIZE(_r)                                                  \
     ((_r)->nr_ents)
index 869c816..24228a1 100644 (file)
@@ -93,6 +93,7 @@ struct xenbus_device_id
 struct xenbus_driver {
        const char *name;       /* defaults to ids[0].devicetype */
        const struct xenbus_device_id *ids;
+       bool allow_rebind; /* avoid setting xenstore closed during remove */
        int (*probe)(struct xenbus_device *dev,
                     const struct xenbus_device_id *id);
        void (*otherend_changed)(struct xenbus_device *dev,
index af9cda8..0ae9cc2 100644 (file)
@@ -387,12 +387,27 @@ static void __init get_fs_names(char *page)
        *s = '\0';
 }
 
-static int __init do_mount_root(char *name, char *fs, int flags, void *data)
+static int __init do_mount_root(const char *name, const char *fs,
+                                const int flags, const void *data)
 {
        struct super_block *s;
-       int err = ksys_mount(name, "/root", fs, flags, data);
-       if (err)
-               return err;
+       struct page *p = NULL;
+       char *data_page = NULL;
+       int ret;
+
+       if (data) {
+               /* do_mount() requires a full page as fifth argument */
+               p = alloc_page(GFP_KERNEL);
+               if (!p)
+                       return -ENOMEM;
+               data_page = page_address(p);
+               /* zero-pad. do_mount() will make sure it's terminated */
+               strncpy(data_page, data, PAGE_SIZE);
+       }
+
+       ret = do_mount(name, "/root", fs, flags, data_page);
+       if (ret)
+               goto out;
 
        ksys_chdir("/root");
        s = current->fs->pwd.dentry->d_sb;
@@ -402,7 +417,11 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
               s->s_type->name,
               sb_rdonly(s) ? " readonly" : "",
               MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
-       return 0;
+
+out:
+       if (p)
+               put_page(p);
+       return ret;
 }
 
 void __init mount_block_root(char *name, int flags)
@@ -670,8 +689,8 @@ void __init prepare_namespace(void)
 
        mount_root();
 out:
-       devtmpfs_mount("dev");
-       ksys_mount(".", "/", NULL, MS_MOVE, NULL);
+       devtmpfs_mount();
+       do_mount(".", "/", NULL, MS_MOVE, NULL);
        ksys_chroot(".");
 }
 
index a9c6cc5..dab8b11 100644 (file)
@@ -48,13 +48,10 @@ early_param("initrd", early_initrd);
 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
        ksys_unshare(CLONE_FS | CLONE_FILES);
-       /* stdin/stdout/stderr for /linuxrc */
-       ksys_open("/dev/console", O_RDWR, 0);
-       ksys_dup(0);
-       ksys_dup(0);
+       console_on_rootfs();
        /* move initrd over / and chdir/chroot in initrd root */
        ksys_chdir("/root");
-       ksys_mount(".", "/", NULL, MS_MOVE, NULL);
+       do_mount(".", "/", NULL, MS_MOVE, NULL);
        ksys_chroot(".");
        ksys_setsid();
        return 0;
@@ -89,7 +86,7 @@ static void __init handle_initrd(void)
        current->flags &= ~PF_FREEZER_SKIP;
 
        /* move initrd to rootfs' /old */
-       ksys_mount("..", ".", NULL, MS_MOVE, NULL);
+       do_mount("..", ".", NULL, MS_MOVE, NULL);
        /* switch root and cwd back to / of rootfs */
        ksys_chroot("..");
 
@@ -103,7 +100,7 @@ static void __init handle_initrd(void)
        mount_root();
 
        printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
-       error = ksys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
+       error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
        if (!error)
                printk("okay\n");
        else {
index 91f6ebb..1ecfd43 100644 (file)
@@ -93,6 +93,7 @@
 #include <linux/rodata_test.h>
 #include <linux/jump_label.h>
 #include <linux/mem_encrypt.h>
+#include <linux/file.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -1155,6 +1156,30 @@ static int __ref kernel_init(void *unused)
              "See Linux Documentation/admin-guide/init.rst for guidance.");
 }
 
+void console_on_rootfs(void)
+{
+       struct file *file;
+       unsigned int i;
+
+       /* Open /dev/console in kernelspace, this should never fail */
+       file = filp_open("/dev/console", O_RDWR, 0);
+       if (IS_ERR(file))
+               goto err_out;
+
+       /* create stdin/stdout/stderr, this should never fail */
+       for (i = 0; i < 3; i++) {
+               if (f_dupfd(i, file, 0) != i)
+                       goto err_out;
+       }
+
+       return;
+
+err_out:
+       /* no panic -- this might not be fatal */
+       pr_err("Warning: unable to open an initial console.\n");
+       return;
+}
+
 static noinline void __init kernel_init_freeable(void)
 {
        /*
@@ -1190,12 +1215,8 @@ static noinline void __init kernel_init_freeable(void)
 
        do_basic_setup();
 
-       /* Open the /dev/console on the rootfs, this should never fail */
-       if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-               pr_err("Warning: unable to open an initial console.\n");
+       console_on_rootfs();
 
-       (void) ksys_dup(0);
-       (void) ksys_dup(0);
        /*
         * check if there is an early userspace init.  If yes, let it do all
         * the work
index d126d15..915eacb 100644 (file)
@@ -100,7 +100,7 @@ device_initcall(ipc_init);
 static const struct rhashtable_params ipc_kht_params = {
        .head_offset            = offsetof(struct kern_ipc_perm, khtnode),
        .key_offset             = offsetof(struct kern_ipc_perm, key),
-       .key_len                = FIELD_SIZEOF(struct kern_ipc_perm, key),
+       .key_len                = sizeof_field(struct kern_ipc_perm, key),
        .automatic_shrinking    = true,
 };
 
index 9f90d3c..4fb20ab 100644 (file)
@@ -1341,7 +1341,7 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct bpf_sysctl_kern, write,
-                                      FIELD_SIZEOF(struct bpf_sysctl_kern,
+                                      sizeof_field(struct bpf_sysctl_kern,
                                                    write),
                                       target_size));
                break;
index 2ba7507..6bd22f6 100644 (file)
@@ -357,7 +357,7 @@ static int cgroup_storage_check_btf(const struct bpf_map *map,
         * The first field must be a 64 bit integer at 0 offset.
         */
        m = (struct btf_member *)(key_type + 1);
-       size = FIELD_SIZEOF(struct bpf_cgroup_storage_key, cgroup_inode_id);
+       size = sizeof_field(struct bpf_cgroup_storage_key, cgroup_inode_id);
        if (!btf_member_is_reg_int(btf, key_type, m, 0, size))
                return -EINVAL;
 
@@ -366,7 +366,7 @@ static int cgroup_storage_check_btf(const struct bpf_map *map,
         */
        m++;
        offset = offsetof(struct bpf_cgroup_storage_key, attach_type);
-       size = FIELD_SIZEOF(struct bpf_cgroup_storage_key, attach_type);
+       size = sizeof_field(struct bpf_cgroup_storage_key, attach_type);
        if (!btf_member_is_reg_int(btf, key_type, m, offset, size))
                return -EINVAL;
 
index 54cc5f9..5352ce5 100644 (file)
@@ -733,9 +733,6 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
  */
 void __sched mutex_unlock(struct mutex *lock)
 {
-#ifdef CONFIG_DEBUG_MUTEXES
-       WARN_ON(in_interrupt());
-#endif
 #ifndef CONFIG_DEBUG_LOCK_ALLOC
        if (__mutex_unlock_fast(lock))
                return;
@@ -1416,7 +1413,6 @@ int __sched mutex_trylock(struct mutex *lock)
 
 #ifdef CONFIG_DEBUG_MUTEXES
        DEBUG_LOCKS_WARN_ON(lock->magic != lock);
-       WARN_ON(in_interrupt());
 #endif
 
        locked = __mutex_trylock(lock);
index 399669f..472dd46 100644 (file)
@@ -51,19 +51,19 @@ EXPORT_SYMBOL(__rwlock_init);
 
 static void spin_dump(raw_spinlock_t *lock, const char *msg)
 {
-       struct task_struct *owner = NULL;
+       struct task_struct *owner = READ_ONCE(lock->owner);
 
-       if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
-               owner = lock->owner;
+       if (owner == SPINLOCK_OWNER_INIT)
+               owner = NULL;
        printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
                msg, raw_smp_processor_id(),
                current->comm, task_pid_nr(current));
        printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, "
                        ".owner_cpu: %d\n",
-               lock, lock->magic,
+               lock, READ_ONCE(lock->magic),
                owner ? owner->comm : "<none>",
                owner ? task_pid_nr(owner) : -1,
-               lock->owner_cpu);
+               READ_ONCE(lock->owner_cpu));
        dump_stack();
 }
 
@@ -80,16 +80,16 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg)
 static inline void
 debug_spin_lock_before(raw_spinlock_t *lock)
 {
-       SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
-       SPIN_BUG_ON(lock->owner == current, lock, "recursion");
-       SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+       SPIN_BUG_ON(READ_ONCE(lock->magic) != SPINLOCK_MAGIC, lock, "bad magic");
+       SPIN_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion");
+       SPIN_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(),
                                                        lock, "cpu recursion");
 }
 
 static inline void debug_spin_lock_after(raw_spinlock_t *lock)
 {
-       lock->owner_cpu = raw_smp_processor_id();
-       lock->owner = current;
+       WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+       WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_spin_unlock(raw_spinlock_t *lock)
@@ -99,8 +99,8 @@ static inline void debug_spin_unlock(raw_spinlock_t *lock)
        SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
        SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
                                                        lock, "wrong CPU");
-       lock->owner = SPINLOCK_OWNER_INIT;
-       lock->owner_cpu = -1;
+       WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+       WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 /*
@@ -187,8 +187,8 @@ static inline void debug_write_lock_before(rwlock_t *lock)
 
 static inline void debug_write_lock_after(rwlock_t *lock)
 {
-       lock->owner_cpu = raw_smp_processor_id();
-       lock->owner = current;
+       WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+       WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_write_unlock(rwlock_t *lock)
@@ -197,8 +197,8 @@ static inline void debug_write_unlock(rwlock_t *lock)
        RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
        RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
                                                        lock, "wrong CPU");
-       lock->owner = SPINLOCK_OWNER_INIT;
-       lock->owner_cpu = -1;
+       WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+       WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 void do_raw_write_lock(rwlock_t *lock)
index 3a486f8..b56f322 100644 (file)
@@ -3730,6 +3730,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
 
        module_enable_ro(mod, false);
        module_enable_nx(mod);
+       module_enable_x(mod);
 
        /* Mark state as coming so strong_try_module_get() ignores us,
         * but kallsyms etc. can see us. */
@@ -3752,11 +3753,6 @@ static int prepare_coming_module(struct module *mod)
        if (err)
                return err;
 
-       /* Make module executable after ftrace is enabled */
-       mutex_lock(&module_mutex);
-       module_enable_x(mod);
-       mutex_unlock(&module_mutex);
-
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_COMING, mod);
        return 0;
index b5dcd1d..7c2fe50 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 2016, Intel Corporation
  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  */
+#include <linux/cpufreq.h>
+
 #include "sched.h"
 
 DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
@@ -57,3 +59,19 @@ void cpufreq_remove_update_util_hook(int cpu)
        rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
 }
 EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);
+
+/**
+ * cpufreq_this_cpu_can_update - Check if cpufreq policy can be updated.
+ * @policy: cpufreq policy to check.
+ *
+ * Return 'true' if:
+ * - the local and remote CPUs share @policy,
+ * - dvfs_possible_from_any_cpu is set in @policy and the local CPU is not going
+ *   offline (in which case it is not expected to run cpufreq updates any more).
+ */
+bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
+{
+       return cpumask_test_cpu(smp_processor_id(), policy->cpus) ||
+               (policy->dvfs_possible_from_any_cpu &&
+                rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data)));
+}
index 322ca88..9b8916f 100644 (file)
@@ -82,12 +82,10 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
         * by the hardware, as calculating the frequency is pointless if
         * we cannot in fact act on it.
         *
-        * For the slow switching platforms, the kthread is always scheduled on
-        * the right set of CPUs and any CPU can find the next frequency and
-        * schedule the kthread.
+        * This is needed on the slow switching platforms too to prevent CPUs
+        * going offline from leaving stale IRQ work items behind.
         */
-       if (sg_policy->policy->fast_switch_enabled &&
-           !cpufreq_this_cpu_can_update(sg_policy->policy))
+       if (!cpufreq_this_cpu_can_update(sg_policy->policy))
                return false;
 
        if (unlikely(sg_policy->limits_changed)) {
index 67e0c46..a265973 100644 (file)
@@ -101,6 +101,15 @@ int function_graph_enter(unsigned long ret, unsigned long func,
 {
        struct ftrace_graph_ent trace;
 
+       /*
+        * Skip graph tracing if the return location is served by direct trampoline,
+        * since call sequence and return addresses is unpredicatable anymore.
+        * Ex: BPF trampoline may call original function and may skip frame
+        * depending on type of BPF programs attached.
+        */
+       if (ftrace_direct_func_count &&
+           ftrace_find_rec_direct(ret - MCOUNT_INSN_SIZE))
+               return -EBUSY;
        trace.func = func;
        trace.depth = ++current->curr_ret_depth;
 
index 74439ab..ac99a35 100644 (file)
@@ -2364,7 +2364,7 @@ int ftrace_direct_func_count;
  * Search the direct_functions hash to see if the given instruction pointer
  * has a direct caller attached to it.
  */
-static unsigned long find_rec_direct(unsigned long ip)
+unsigned long ftrace_find_rec_direct(unsigned long ip)
 {
        struct ftrace_func_entry *entry;
 
@@ -2380,7 +2380,7 @@ static void call_direct_funcs(unsigned long ip, unsigned long pip,
 {
        unsigned long addr;
 
-       addr = find_rec_direct(ip);
+       addr = ftrace_find_rec_direct(ip);
        if (!addr)
                return;
 
@@ -2393,11 +2393,6 @@ struct ftrace_ops direct_ops = {
                          | FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS
                          | FTRACE_OPS_FL_PERMANENT,
 };
-#else
-static inline unsigned long find_rec_direct(unsigned long ip)
-{
-       return 0;
-}
 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
 
 /**
@@ -2417,7 +2412,7 @@ unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec)
 
        if ((rec->flags & FTRACE_FL_DIRECT) &&
            (ftrace_rec_count(rec) == 1)) {
-               addr = find_rec_direct(rec->ip);
+               addr = ftrace_find_rec_direct(rec->ip);
                if (addr)
                        return addr;
                WARN_ON_ONCE(1);
@@ -2458,7 +2453,7 @@ unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec)
 
        /* Direct calls take precedence over trampolines */
        if (rec->flags & FTRACE_FL_DIRECT_EN) {
-               addr = find_rec_direct(rec->ip);
+               addr = ftrace_find_rec_direct(rec->ip);
                if (addr)
                        return addr;
                WARN_ON_ONCE(1);
@@ -3604,7 +3599,7 @@ static int t_show(struct seq_file *m, void *v)
                if (rec->flags & FTRACE_FL_DIRECT) {
                        unsigned long direct;
 
-                       direct = find_rec_direct(rec->ip);
+                       direct = ftrace_find_rec_direct(rec->ip);
                        if (direct)
                                seq_printf(m, "\n\tdirect-->%pS", (void *)direct);
                }
@@ -5008,7 +5003,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
        mutex_lock(&direct_mutex);
 
        /* See if there's a direct function at @ip already */
-       if (find_rec_direct(ip))
+       if (ftrace_find_rec_direct(ip))
                goto out_unlock;
 
        ret = -ENODEV;
@@ -5027,7 +5022,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
        if (ip != rec->ip) {
                ip = rec->ip;
                /* Need to check this ip for a direct. */
-               if (find_rec_direct(ip))
+               if (ftrace_find_rec_direct(ip))
                        goto out_unlock;
        }
 
index 4bf050f..3f65537 100644 (file)
@@ -5070,7 +5070,7 @@ static __init int test_ringbuffer(void)
        int ret = 0;
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Lockdown is enabled, skipping ring buffer tests\n");
+               pr_warn("Lockdown is enabled, skipping ring buffer tests\n");
                return 0;
        }
 
index 23459d5..6c75410 100644 (file)
@@ -1889,7 +1889,7 @@ int __init register_tracer(struct tracer *type)
        }
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Can not register tracer %s due to lockdown\n",
+               pr_warn("Can not register tracer %s due to lockdown\n",
                           type->name);
                return -EPERM;
        }
@@ -8796,7 +8796,7 @@ struct dentry *tracing_init_dentry(void)
        struct trace_array *tr = &global_trace;
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Tracing disabled due to lockdown\n");
+               pr_warn("Tracing disabled due to lockdown\n");
                return ERR_PTR(-EPERM);
        }
 
@@ -9244,7 +9244,7 @@ __init static int tracer_alloc_buffers(void)
 
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Tracing disabled due to lockdown\n");
+               pr_warn("Tracing disabled due to lockdown\n");
                return -EPERM;
        }
 
index d437107..d45079e 100644 (file)
@@ -17,12 +17,10 @@ static int
 trace_inject_entry(struct trace_event_file *file, void *rec, int len)
 {
        struct trace_event_buffer fbuffer;
-       struct ring_buffer *buffer;
        int written = 0;
        void *entry;
 
        rcu_read_lock_sched();
-       buffer = file->tr->trace_buffer.buffer;
        entry = trace_event_buffer_reserve(&fbuffer, file, len);
        if (entry) {
                memcpy(entry, rec, len);
index bc88fd9..cfc9235 100644 (file)
@@ -4374,8 +4374,8 @@ void destroy_workqueue(struct workqueue_struct *wq)
        for_each_pwq(pwq, wq) {
                spin_lock_irq(&pwq->pool->lock);
                if (WARN_ON(pwq_busy(pwq))) {
-                       pr_warning("%s: %s has the following busy pwq\n",
-                                  __func__, wq->name);
+                       pr_warn("%s: %s has the following busy pwq\n",
+                               __func__, wq->name);
                        show_pwq(pwq);
                        spin_unlock_irq(&pwq->pool->lock);
                        mutex_unlock(&wq->mutex);
index d1842fe..5ffe144 100644 (file)
@@ -1483,6 +1483,55 @@ config PROVIDE_OHCI1394_DMA_INIT
 
          See Documentation/debugging-via-ohci1394.txt for more information.
 
+source "samples/Kconfig"
+
+config ARCH_HAS_DEVMEM_IS_ALLOWED
+       bool
+
+config STRICT_DEVMEM
+       bool "Filter access to /dev/mem"
+       depends on MMU && DEVMEM
+       depends on ARCH_HAS_DEVMEM_IS_ALLOWED
+       default y if PPC || X86 || ARM64
+       help
+         If this option is disabled, you allow userspace (root) access to all
+         of memory, including kernel and userspace memory. Accidental
+         access to this is obviously disastrous, but specific access can
+         be used by people debugging the kernel. Note that with PAT support
+         enabled, even in this case there are restrictions on /dev/mem
+         use due to the cache aliasing requirements.
+
+         If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
+         file only allows userspace access to PCI space and the BIOS code and
+         data regions.  This is sufficient for dosemu and X and all common
+         users of /dev/mem.
+
+         If in doubt, say Y.
+
+config IO_STRICT_DEVMEM
+       bool "Filter I/O access to /dev/mem"
+       depends on STRICT_DEVMEM
+       help
+         If this option is disabled, you allow userspace (root) access to all
+         io-memory regardless of whether a driver is actively using that
+         range.  Accidental access to this is obviously disastrous, but
+         specific access can be used by people debugging kernel drivers.
+
+         If this option is switched on, the /dev/mem file only allows
+         userspace access to *idle* io-memory ranges (see /proc/iomem) This
+         may break traditional users of /dev/mem (dosemu, legacy X, etc...)
+         if the driver using a given range cannot be disabled.
+
+         If in doubt, say Y.
+
+menu "$(SRCARCH) Debugging"
+
+source "arch/$(SRCARCH)/Kconfig.debug"
+
+endmenu
+
+menu "Kernel Testing and Coverage"
+
 source "lib/kunit/Kconfig"
 
 config NOTIFIER_ERROR_INJECTION
@@ -1643,10 +1692,6 @@ config FAULT_INJECTION_STACKTRACE_FILTER
        help
          Provide stacktrace filter for fault-injection capabilities
 
-endmenu # "Kernel Testing and Coverage"
-
-menu "Kernel Testing and Coverage"
-
 config ARCH_HAS_KCOV
        bool
        help
@@ -2130,52 +2175,7 @@ config MEMTEST
                memtest=17, mean do 17 test patterns.
          If you are unsure how to answer this question, answer N.
 
-source "samples/Kconfig"
-
-config ARCH_HAS_DEVMEM_IS_ALLOWED
-       bool
-
-config STRICT_DEVMEM
-       bool "Filter access to /dev/mem"
-       depends on MMU && DEVMEM
-       depends on ARCH_HAS_DEVMEM_IS_ALLOWED
-       default y if PPC || X86 || ARM64
-       ---help---
-         If this option is disabled, you allow userspace (root) access to all
-         of memory, including kernel and userspace memory. Accidental
-         access to this is obviously disastrous, but specific access can
-         be used by people debugging the kernel. Note that with PAT support
-         enabled, even in this case there are restrictions on /dev/mem
-         use due to the cache aliasing requirements.
-
-         If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
-         file only allows userspace access to PCI space and the BIOS code and
-         data regions.  This is sufficient for dosemu and X and all common
-         users of /dev/mem.
-
-         If in doubt, say Y.
 
-config IO_STRICT_DEVMEM
-       bool "Filter I/O access to /dev/mem"
-       depends on STRICT_DEVMEM
-       ---help---
-         If this option is disabled, you allow userspace (root) access to all
-         io-memory regardless of whether a driver is actively using that
-         range.  Accidental access to this is obviously disastrous, but
-         specific access can be used by people debugging kernel drivers.
-
-         If this option is switched on, the /dev/mem file only allows
-         userspace access to *idle* io-memory ranges (see /proc/iomem) This
-         may break traditional users of /dev/mem (dosemu, legacy X, etc...)
-         if the driver using a given range cannot be disabled.
-
-         If in doubt, say Y.
-
-menu "$(SRCARCH) Debugging"
-
-source "arch/$(SRCARCH)/Kconfig.debug"
-
-endmenu
 
 config HYPERV_TESTING
        bool "Microsoft Hyper-V driver testing"
@@ -2184,4 +2184,6 @@ config HYPERV_TESTING
        help
          Select this option to enable Hyper-V vmbus testing.
 
+endmenu # "Kernel Testing and Coverage"
+
 endmenu # Kernel hacking
index c6aa036..0809805 100644 (file)
@@ -13,7 +13,7 @@ BEGIN {
        for (i = 0; i < rep; ++i) {
                tmp = $0
                gsub(/\$\$/, i, tmp)
-               gsub(/\$\#/, n, tmp)
+               gsub(/\$#/, n, tmp)
                gsub(/\$\*/, "$", tmp)
                print tmp
        }
index 2fa710b..c15d8ae 100644 (file)
@@ -778,15 +778,17 @@ static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,
        return 0;
 }
 
-int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
+int kasan_populate_vmalloc(unsigned long addr, unsigned long size)
 {
        unsigned long shadow_start, shadow_end;
        int ret;
 
-       shadow_start = (unsigned long)kasan_mem_to_shadow(area->addr);
+       if (!is_vmalloc_or_module_addr((void *)addr))
+               return 0;
+
+       shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr);
        shadow_start = ALIGN_DOWN(shadow_start, PAGE_SIZE);
-       shadow_end = (unsigned long)kasan_mem_to_shadow(area->addr +
-                                                       area->size);
+       shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size);
        shadow_end = ALIGN(shadow_end, PAGE_SIZE);
 
        ret = apply_to_page_range(&init_mm, shadow_start,
@@ -797,10 +799,6 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
 
        flush_cache_vmap(shadow_start, shadow_end);
 
-       kasan_unpoison_shadow(area->addr, requested_size);
-
-       area->flags |= VM_KASAN;
-
        /*
         * We need to be careful about inter-cpu effects here. Consider:
         *
@@ -843,12 +841,23 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
  * Poison the shadow for a vmalloc region. Called as part of the
  * freeing process at the time the region is freed.
  */
-void kasan_poison_vmalloc(void *start, unsigned long size)
+void kasan_poison_vmalloc(const void *start, unsigned long size)
 {
+       if (!is_vmalloc_or_module_addr(start))
+               return;
+
        size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
        kasan_poison_shadow(start, size, KASAN_VMALLOC_INVALID);
 }
 
+void kasan_unpoison_vmalloc(const void *start, unsigned long size)
+{
+       if (!is_vmalloc_or_module_addr(start))
+               return;
+
+       kasan_unpoison_shadow(start, size);
+}
+
 static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr,
                                        void *unused)
 {
@@ -948,6 +957,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
 {
        void *shadow_start, *shadow_end;
        unsigned long region_start, region_end;
+       unsigned long size;
 
        region_start = ALIGN(start, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
        region_end = ALIGN_DOWN(end, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
@@ -970,9 +980,11 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
        shadow_end = kasan_mem_to_shadow((void *)region_end);
 
        if (shadow_end > shadow_start) {
-               apply_to_page_range(&init_mm, (unsigned long)shadow_start,
-                                   (unsigned long)(shadow_end - shadow_start),
-                                   kasan_depopulate_vmalloc_pte, NULL);
+               size = shadow_end - shadow_start;
+               apply_to_existing_page_range(&init_mm,
+                                            (unsigned long)shadow_start,
+                                            size, kasan_depopulate_vmalloc_pte,
+                                            NULL);
                flush_tlb_kernel_range((unsigned long)shadow_start,
                                       (unsigned long)shadow_end);
        }
index 606da18..45442d9 100644 (file)
@@ -2021,26 +2021,34 @@ EXPORT_SYMBOL(vm_iomap_memory);
 
 static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pte_t *pte;
-       int err;
+       int err = 0;
        spinlock_t *uninitialized_var(ptl);
 
-       pte = (mm == &init_mm) ?
-               pte_alloc_kernel(pmd, addr) :
-               pte_alloc_map_lock(mm, pmd, addr, &ptl);
-       if (!pte)
-               return -ENOMEM;
+       if (create) {
+               pte = (mm == &init_mm) ?
+                       pte_alloc_kernel(pmd, addr) :
+                       pte_alloc_map_lock(mm, pmd, addr, &ptl);
+               if (!pte)
+                       return -ENOMEM;
+       } else {
+               pte = (mm == &init_mm) ?
+                       pte_offset_kernel(pmd, addr) :
+                       pte_offset_map_lock(mm, pmd, addr, &ptl);
+       }
 
        BUG_ON(pmd_huge(*pmd));
 
        arch_enter_lazy_mmu_mode();
 
        do {
-               err = fn(pte++, addr, data);
-               if (err)
-                       break;
+               if (create || !pte_none(*pte)) {
+                       err = fn(pte++, addr, data);
+                       if (err)
+                               break;
+               }
        } while (addr += PAGE_SIZE, addr != end);
 
        arch_leave_lazy_mmu_mode();
@@ -2052,77 +2060,95 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
 
 static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pmd_t *pmd;
        unsigned long next;
-       int err;
+       int err = 0;
 
        BUG_ON(pud_huge(*pud));
 
-       pmd = pmd_alloc(mm, pud, addr);
-       if (!pmd)
-               return -ENOMEM;
+       if (create) {
+               pmd = pmd_alloc(mm, pud, addr);
+               if (!pmd)
+                       return -ENOMEM;
+       } else {
+               pmd = pmd_offset(pud, addr);
+       }
        do {
                next = pmd_addr_end(addr, end);
-               err = apply_to_pte_range(mm, pmd, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !pmd_none_or_clear_bad(pmd)) {
+                       err = apply_to_pte_range(mm, pmd, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (pmd++, addr = next, addr != end);
        return err;
 }
 
 static int apply_to_pud_range(struct mm_struct *mm, p4d_t *p4d,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pud_t *pud;
        unsigned long next;
-       int err;
+       int err = 0;
 
-       pud = pud_alloc(mm, p4d, addr);
-       if (!pud)
-               return -ENOMEM;
+       if (create) {
+               pud = pud_alloc(mm, p4d, addr);
+               if (!pud)
+                       return -ENOMEM;
+       } else {
+               pud = pud_offset(p4d, addr);
+       }
        do {
                next = pud_addr_end(addr, end);
-               err = apply_to_pmd_range(mm, pud, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !pud_none_or_clear_bad(pud)) {
+                       err = apply_to_pmd_range(mm, pud, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (pud++, addr = next, addr != end);
        return err;
 }
 
 static int apply_to_p4d_range(struct mm_struct *mm, pgd_t *pgd,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        p4d_t *p4d;
        unsigned long next;
-       int err;
+       int err = 0;
 
-       p4d = p4d_alloc(mm, pgd, addr);
-       if (!p4d)
-               return -ENOMEM;
+       if (create) {
+               p4d = p4d_alloc(mm, pgd, addr);
+               if (!p4d)
+                       return -ENOMEM;
+       } else {
+               p4d = p4d_offset(pgd, addr);
+       }
        do {
                next = p4d_addr_end(addr, end);
-               err = apply_to_pud_range(mm, p4d, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !p4d_none_or_clear_bad(p4d)) {
+                       err = apply_to_pud_range(mm, p4d, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (p4d++, addr = next, addr != end);
        return err;
 }
 
-/*
- * Scan a region of virtual memory, filling in page tables as necessary
- * and calling a provided function on each leaf page table.
- */
-int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
-                       unsigned long size, pte_fn_t fn, void *data)
+static int __apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                                unsigned long size, pte_fn_t fn,
+                                void *data, bool create)
 {
        pgd_t *pgd;
        unsigned long next;
        unsigned long end = addr + size;
-       int err;
+       int err = 0;
 
        if (WARN_ON(addr >= end))
                return -EINVAL;
@@ -2130,16 +2156,42 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
        pgd = pgd_offset(mm, addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = apply_to_p4d_range(mm, pgd, addr, next, fn, data);
+               if (!create && pgd_none_or_clear_bad(pgd))
+                       continue;
+               err = apply_to_p4d_range(mm, pgd, addr, next, fn, data, create);
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
 
        return err;
 }
+
+/*
+ * Scan a region of virtual memory, filling in page tables as necessary
+ * and calling a provided function on each leaf page table.
+ */
+int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                       unsigned long size, pte_fn_t fn, void *data)
+{
+       return __apply_to_page_range(mm, addr, size, fn, data, true);
+}
 EXPORT_SYMBOL_GPL(apply_to_page_range);
 
 /*
+ * Scan a region of virtual memory, calling a provided function on
+ * each leaf page table where it exists.
+ *
+ * Unlike apply_to_page_range, this does _not_ fill in page tables
+ * where they are absent.
+ */
+int apply_to_existing_page_range(struct mm_struct *mm, unsigned long addr,
+                                unsigned long size, pte_fn_t fn, void *data)
+{
+       return __apply_to_page_range(mm, addr, size, fn, data, false);
+}
+EXPORT_SYMBOL_GPL(apply_to_existing_page_range);
+
+/*
  * handle_pte_fault chooses page fault handler according to an entry which was
  * read non-atomically.  Before making any commitment, on those architectures
  * or configurations (e.g. i386 with PAE) which might give a mix of unmatched
index 4d3b3d6..e9681dc 100644 (file)
@@ -1062,6 +1062,26 @@ __alloc_vmap_area(unsigned long size, unsigned long align,
 }
 
 /*
+ * Free a region of KVA allocated by alloc_vmap_area
+ */
+static void free_vmap_area(struct vmap_area *va)
+{
+       /*
+        * Remove from the busy tree/list.
+        */
+       spin_lock(&vmap_area_lock);
+       unlink_va(va, &vmap_area_root);
+       spin_unlock(&vmap_area_lock);
+
+       /*
+        * Insert/Merge it back to the free tree/list.
+        */
+       spin_lock(&free_vmap_area_lock);
+       merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list);
+       spin_unlock(&free_vmap_area_lock);
+}
+
+/*
  * Allocate a region of KVA of the specified size and alignment, within the
  * vstart and vend.
  */
@@ -1073,6 +1093,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
        struct vmap_area *va, *pva;
        unsigned long addr;
        int purged = 0;
+       int ret;
 
        BUG_ON(!size);
        BUG_ON(offset_in_page(size));
@@ -1139,6 +1160,7 @@ retry:
        va->va_end = addr + size;
        va->vm = NULL;
 
+
        spin_lock(&vmap_area_lock);
        insert_vmap_area(va, &vmap_area_root, &vmap_area_list);
        spin_unlock(&vmap_area_lock);
@@ -1147,6 +1169,12 @@ retry:
        BUG_ON(va->va_start < vstart);
        BUG_ON(va->va_end > vend);
 
+       ret = kasan_populate_vmalloc(addr, size);
+       if (ret) {
+               free_vmap_area(va);
+               return ERR_PTR(ret);
+       }
+
        return va;
 
 overflow:
@@ -1186,26 +1214,6 @@ int unregister_vmap_purge_notifier(struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(unregister_vmap_purge_notifier);
 
 /*
- * Free a region of KVA allocated by alloc_vmap_area
- */
-static void free_vmap_area(struct vmap_area *va)
-{
-       /*
-        * Remove from the busy tree/list.
-        */
-       spin_lock(&vmap_area_lock);
-       unlink_va(va, &vmap_area_root);
-       spin_unlock(&vmap_area_lock);
-
-       /*
-        * Insert/Merge it back to the free tree/list.
-        */
-       spin_lock(&free_vmap_area_lock);
-       merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list);
-       spin_unlock(&free_vmap_area_lock);
-}
-
-/*
  * Clear the pagetable entries of a given vmap_area
  */
 static void unmap_vmap_area(struct vmap_area *va)
@@ -1771,6 +1779,8 @@ void vm_unmap_ram(const void *mem, unsigned int count)
        BUG_ON(addr > VMALLOC_END);
        BUG_ON(!PAGE_ALIGNED(addr));
 
+       kasan_poison_vmalloc(mem, size);
+
        if (likely(count <= VMAP_MAX_ALLOC)) {
                debug_check_no_locks_freed(mem, size);
                vb_free(mem, size);
@@ -1821,6 +1831,9 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
                addr = va->va_start;
                mem = (void *)addr;
        }
+
+       kasan_unpoison_vmalloc(mem, size);
+
        if (vmap_page_range(addr, addr + size, prot, pages) < 0) {
                vm_unmap_ram(mem, count);
                return NULL;
@@ -2075,6 +2088,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
 {
        struct vmap_area *va;
        struct vm_struct *area;
+       unsigned long requested_size = size;
 
        BUG_ON(in_interrupt());
        size = PAGE_ALIGN(size);
@@ -2098,23 +2112,9 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
                return NULL;
        }
 
-       setup_vmalloc_vm(area, va, flags, caller);
+       kasan_unpoison_vmalloc((void *)va->va_start, requested_size);
 
-       /*
-        * For KASAN, if we are in vmalloc space, we need to cover the shadow
-        * area with real memory. If we come here through VM_ALLOC, this is
-        * done by a higher level function that has access to the true size,
-        * which might not be a full page.
-        *
-        * We assume module space comes via VM_ALLOC path.
-        */
-       if (is_vmalloc_addr(area->addr) && !(area->flags & VM_ALLOC)) {
-               if (kasan_populate_vmalloc(area->size, area)) {
-                       unmap_vmap_area(va);
-                       kfree(area);
-                       return NULL;
-               }
-       }
+       setup_vmalloc_vm(area, va, flags, caller);
 
        return area;
 }
@@ -2293,8 +2293,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
        debug_check_no_locks_freed(area->addr, get_vm_area_size(area));
        debug_check_no_obj_freed(area->addr, get_vm_area_size(area));
 
-       if (area->flags & VM_KASAN)
-               kasan_poison_vmalloc(area->addr, area->size);
+       kasan_poison_vmalloc(area->addr, area->size);
 
        vm_remove_mappings(area, deallocate_pages);
 
@@ -2539,7 +2538,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!size || (size >> PAGE_SHIFT) > totalram_pages())
                goto fail;
 
-       area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
+       area = __get_vm_area_node(real_size, align, VM_ALLOC | VM_UNINITIALIZED |
                                vm_flags, start, end, node, gfp_mask, caller);
        if (!area)
                goto fail;
@@ -2548,11 +2547,6 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!addr)
                return NULL;
 
-       if (is_vmalloc_or_module_addr(area->addr)) {
-               if (kasan_populate_vmalloc(real_size, area))
-                       return NULL;
-       }
-
        /*
         * In this function, newly allocated vm_struct has VM_UNINITIALIZED
         * flag. It means that vm_struct is not fully initialized.
@@ -3294,7 +3288,7 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
        struct vmap_area **vas, *va;
        struct vm_struct **vms;
        int area, area2, last_area, term_area;
-       unsigned long base, start, size, end, last_end;
+       unsigned long base, start, size, end, last_end, orig_start, orig_end;
        bool purged = false;
        enum fit_type type;
 
@@ -3424,6 +3418,15 @@ retry:
 
        spin_unlock(&free_vmap_area_lock);
 
+       /* populate the kasan shadow space */
+       for (area = 0; area < nr_vms; area++) {
+               if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area]))
+                       goto err_free_shadow;
+
+               kasan_unpoison_vmalloc((void *)vas[area]->va_start,
+                                      sizes[area]);
+       }
+
        /* insert all vm's */
        spin_lock(&vmap_area_lock);
        for (area = 0; area < nr_vms; area++) {
@@ -3434,12 +3437,6 @@ retry:
        }
        spin_unlock(&vmap_area_lock);
 
-       /* populate the shadow space outside of the lock */
-       for (area = 0; area < nr_vms; area++) {
-               /* assume success here */
-               kasan_populate_vmalloc(sizes[area], vms[area]);
-       }
-
        kfree(vas);
        return vms;
 
@@ -3451,8 +3448,12 @@ recovery:
         * and when pcpu_get_vm_areas() is success.
         */
        while (area--) {
-               merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
-                                      &free_vmap_area_list);
+               orig_start = vas[area]->va_start;
+               orig_end = vas[area]->va_end;
+               va = merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
+                                           &free_vmap_area_list);
+               kasan_release_vmalloc(orig_start, orig_end,
+                                     va->va_start, va->va_end);
                vas[area] = NULL;
        }
 
@@ -3487,6 +3488,28 @@ err_free2:
        kfree(vas);
        kfree(vms);
        return NULL;
+
+err_free_shadow:
+       spin_lock(&free_vmap_area_lock);
+       /*
+        * We release all the vmalloc shadows, even the ones for regions that
+        * hadn't been successfully added. This relies on kasan_release_vmalloc
+        * being able to tolerate this case.
+        */
+       for (area = 0; area < nr_vms; area++) {
+               orig_start = vas[area]->va_start;
+               orig_end = vas[area]->va_end;
+               va = merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
+                                           &free_vmap_area_list);
+               kasan_release_vmalloc(orig_start, orig_end,
+                                     va->va_start, va->va_end);
+               vas[area] = NULL;
+               kfree(vms[area]);
+       }
+       spin_unlock(&free_vmap_area_lock);
+       kfree(vas);
+       kfree(vms);
+       return NULL;
 }
 
 /**
index 74e8edc..572fb17 100644 (file)
@@ -387,7 +387,7 @@ void register_shrinker_prepared(struct shrinker *shrinker)
 {
        down_write(&shrinker_rwsem);
        list_add_tail(&shrinker->list, &shrinker_list);
-#ifdef CONFIG_MEMCG_KMEM
+#ifdef CONFIG_MEMCG
        if (shrinker->flags & SHRINKER_MEMCG_AWARE)
                idr_replace(&shrinker_idr, shrinker, shrinker->id);
 #endif
index 2cfdfbf..bea6e43 100644 (file)
@@ -523,7 +523,7 @@ int mrp_request_join(const struct net_device *dev,
        struct mrp_attr *attr;
 
        if (sizeof(struct mrp_skb_cb) + len >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return -ENOMEM;
 
        spin_lock_bh(&app->lock);
@@ -548,7 +548,7 @@ void mrp_request_leave(const struct net_device *dev,
        struct mrp_attr *attr;
 
        if (sizeof(struct mrp_skb_cb) + len >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return;
 
        spin_lock_bh(&app->lock);
@@ -692,7 +692,7 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
         * advance to the next event in its Vector.
         */
        if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return -1;
        if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue,
                          mrp_cb(skb)->mh->attrlen) < 0)
index 4a89177..4811ec6 100644 (file)
@@ -548,7 +548,7 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12);
        BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8);
 
-       i = FIELD_SIZEOF(struct sk_buff, cb);
+       i = sizeof_field(struct sk_buff, cb);
        BUILD_BUG_ON(sizeof(struct batadv_skb_cb) > i);
 
        /* broadcast packet */
index 915c2d6..f79205d 100644 (file)
@@ -253,21 +253,21 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb)
        /* priority is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, priority) +
-                          FIELD_SIZEOF(struct __sk_buff, priority),
+                          sizeof_field(struct __sk_buff, priority),
                           offsetof(struct __sk_buff, cb)))
                return -EINVAL;
 
        /* cb is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, cb) +
-                          FIELD_SIZEOF(struct __sk_buff, cb),
+                          sizeof_field(struct __sk_buff, cb),
                           offsetof(struct __sk_buff, tstamp)))
                return -EINVAL;
 
        /* tstamp is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, tstamp) +
-                          FIELD_SIZEOF(struct __sk_buff, tstamp),
+                          sizeof_field(struct __sk_buff, tstamp),
                           sizeof(struct __sk_buff)))
                return -EINVAL;
 
@@ -438,7 +438,7 @@ static int verify_user_bpf_flow_keys(struct bpf_flow_keys *ctx)
        /* flags is allowed */
 
        if (!range_is_zero(ctx, offsetof(struct bpf_flow_keys, flags) +
-                          FIELD_SIZEOF(struct bpf_flow_keys, flags),
+                          sizeof_field(struct bpf_flow_keys, flags),
                           sizeof(struct bpf_flow_keys)))
                return -EINVAL;
 
index 8a8f9e5..b6fe30e 100644 (file)
@@ -312,7 +312,7 @@ static int __init br_init(void)
 {
        int err;
 
-       BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > sizeof_field(struct sk_buff, cb));
 
        err = stp_proto_register(&br_stp_proto);
        if (err < 0) {
index 2c277b8..0ad39c8 100644 (file)
@@ -10165,7 +10165,7 @@ static struct hlist_head * __net_init netdev_create_hash(void)
 static int __net_init netdev_init(struct net *net)
 {
        BUILD_BUG_ON(GRO_HASH_BUCKETS >
-                    8 * FIELD_SIZEOF(struct napi_struct, gro_bitmask));
+                    8 * sizeof_field(struct napi_struct, gro_bitmask));
 
        if (net != &init_net)
                INIT_LIST_HEAD(&net->dev_base_head);
index f1e703e..c19dd09 100644 (file)
@@ -274,7 +274,7 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
 
        switch (skb_field) {
        case SKF_AD_MARK:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, mark) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
                                      offsetof(struct sk_buff, mark));
@@ -289,14 +289,14 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
                break;
 
        case SKF_AD_QUEUE:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, queue_mapping) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
                                      offsetof(struct sk_buff, queue_mapping));
                break;
 
        case SKF_AD_VLAN_TAG:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_tci) != 2);
 
                /* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
                *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
@@ -322,7 +322,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
 
        switch (fp->k) {
        case SKF_AD_OFF + SKF_AD_PROTOCOL:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, protocol) != 2);
 
                /* A = *(u16 *) (CTX + offsetof(protocol)) */
                *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
@@ -338,8 +338,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
 
        case SKF_AD_OFF + SKF_AD_IFINDEX:
        case SKF_AD_OFF + SKF_AD_HATYPE:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
-               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
+               BUILD_BUG_ON(sizeof_field(struct net_device, ifindex) != 4);
+               BUILD_BUG_ON(sizeof_field(struct net_device, type) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, dev),
                                      BPF_REG_TMP, BPF_REG_CTX,
@@ -361,7 +361,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
                break;
 
        case SKF_AD_OFF + SKF_AD_RXHASH:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, hash) != 4);
 
                *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX,
                                    offsetof(struct sk_buff, hash));
@@ -385,7 +385,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
                break;
 
        case SKF_AD_OFF + SKF_AD_VLAN_TPID:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_proto) != 2);
 
                /* A = *(u16 *) (CTX + offsetof(vlan_proto)) */
                *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
@@ -5589,8 +5589,8 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_TCP_SOCK_GET_COMMON(FIELD)                                 \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, FIELD) >     \
-                            FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, FIELD) >     \
+                            sizeof_field(struct bpf_tcp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct tcp_sock, FIELD),\
                                      si->dst_reg, si->src_reg,         \
                                      offsetof(struct tcp_sock, FIELD)); \
@@ -5598,9 +5598,9 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_INET_SOCK_GET_COMMON(FIELD)                                        \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct inet_connection_sock,  \
+               BUILD_BUG_ON(sizeof_field(struct inet_connection_sock,  \
                                          FIELD) >                      \
-                            FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
+                            sizeof_field(struct bpf_tcp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                 \
                                        struct inet_connection_sock,    \
                                        FIELD),                         \
@@ -5615,7 +5615,7 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
        switch (si->off) {
        case offsetof(struct bpf_tcp_sock, rtt_min):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, rtt_min) !=
                             sizeof(struct minmax));
                BUILD_BUG_ON(sizeof(struct minmax) <
                             sizeof(struct minmax_sample));
@@ -5780,8 +5780,8 @@ u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_XDP_SOCK_GET(FIELD)                                                \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) >     \
-                            FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \
+               BUILD_BUG_ON(sizeof_field(struct xdp_sock, FIELD) >     \
+                            sizeof_field(struct bpf_xdp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\
                                      si->dst_reg, si->src_reg,         \
                                      offsetof(struct xdp_sock, FIELD)); \
@@ -7344,7 +7344,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
 
        case offsetof(struct __sk_buff, cb[0]) ...
             offsetofend(struct __sk_buff, cb[4]) - 1:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, data) < 20);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, data) < 20);
                BUILD_BUG_ON((offsetof(struct sk_buff, cb) +
                              offsetof(struct qdisc_skb_cb, data)) %
                             sizeof(__u64));
@@ -7363,7 +7363,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, tc_classid):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, tc_classid) != 2);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, tc_classid) != 2);
 
                off  = si->off;
                off -= offsetof(struct __sk_buff, tc_classid);
@@ -7434,7 +7434,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
 #endif
                break;
        case offsetof(struct __sk_buff, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7445,7 +7445,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     2, target_size));
                break;
        case offsetof(struct __sk_buff, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7456,7 +7456,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     4, target_size));
                break;
        case offsetof(struct __sk_buff, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
@@ -7470,7 +7470,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, remote_ip6[0]) ...
             offsetof(struct __sk_buff, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -7490,7 +7490,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, local_ip6[0]) ...
             offsetof(struct __sk_buff, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -7509,7 +7509,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7524,7 +7524,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7535,7 +7535,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, tstamp):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tstamp) != 8);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, tstamp) != 8);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_DW,
@@ -7573,7 +7573,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     target_size));
                break;
        case offsetof(struct __sk_buff, wire_len):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, pkt_len) != 4);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, pkt_len) != 4);
 
                off = si->off;
                off -= offsetof(struct __sk_buff, wire_len);
@@ -7603,7 +7603,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
 
        switch (si->off) {
        case offsetof(struct bpf_sock, bound_dev_if):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_bound_dev_if) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_bound_dev_if) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7614,7 +7614,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock, mark):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_mark) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_mark) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7625,7 +7625,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock, priority):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_priority) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_priority) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7641,7 +7641,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common,
                                       skc_family,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_family),
                                       target_size));
                break;
@@ -7668,7 +7668,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_rcv_saddr,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_rcv_saddr),
                                       target_size));
                break;
@@ -7677,7 +7677,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_daddr,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_daddr),
                                       target_size));
                break;
@@ -7691,7 +7691,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        bpf_target_off(
                                struct sock_common,
                                skc_v6_rcv_saddr.s6_addr32[0],
-                               FIELD_SIZEOF(struct sock_common,
+                               sizeof_field(struct sock_common,
                                             skc_v6_rcv_saddr.s6_addr32[0]),
                                target_size) + off);
 #else
@@ -7708,7 +7708,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common,
                                       skc_v6_daddr.s6_addr32[0],
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_v6_daddr.s6_addr32[0]),
                                       target_size) + off);
 #else
@@ -7722,7 +7722,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_num),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_num,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_num),
                                       target_size));
                break;
@@ -7732,7 +7732,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_dport),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_dport,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_dport),
                                       target_size));
                break;
@@ -7742,7 +7742,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_state),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_state,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_state),
                                       target_size));
                break;
@@ -7837,7 +7837,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                                      si->src_reg, offsetof(S, F));            \
                *insn++ = BPF_LDX_MEM(                                         \
                        SIZE, si->dst_reg, si->dst_reg,                        \
-                       bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF),           \
+                       bpf_target_off(NS, NF, sizeof_field(NS, NF),           \
                                       target_size)                            \
                                + OFF);                                        \
        } while (0)
@@ -7868,7 +7868,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), tmp_reg,         \
                                      si->dst_reg, offsetof(S, F));            \
                *insn++ = BPF_STX_MEM(SIZE, tmp_reg, si->src_reg,              \
-                       bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF),           \
+                       bpf_target_off(NS, NF, sizeof_field(NS, NF),           \
                                       target_size)                            \
                                + OFF);                                        \
                *insn++ = BPF_LDX_MEM(BPF_DW, tmp_reg, si->dst_reg,            \
@@ -7930,8 +7930,8 @@ static u32 sock_addr_convert_ctx_access(enum bpf_access_type type,
                 */
                BUILD_BUG_ON(offsetof(struct sockaddr_in, sin_port) !=
                             offsetof(struct sockaddr_in6, sin6_port));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sockaddr_in, sin_port) !=
-                            FIELD_SIZEOF(struct sockaddr_in6, sin6_port));
+               BUILD_BUG_ON(sizeof_field(struct sockaddr_in, sin_port) !=
+                            sizeof_field(struct sockaddr_in6, sin6_port));
                SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD(struct bpf_sock_addr_kern,
                                                     struct sockaddr_in6, uaddr,
                                                     sin6_port, tmp_reg);
@@ -7997,8 +7997,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 /* Helper macro for adding read access to tcp_sock or sock fields. */
 #define SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ)                        \
        do {                                                                  \
-               BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) >                   \
-                            FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD));   \
+               BUILD_BUG_ON(sizeof_field(OBJ, OBJ_FIELD) >                   \
+                            sizeof_field(struct bpf_sock_ops, BPF_FIELD));   \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                       \
                                                struct bpf_sock_ops_kern,     \
                                                is_fullsock),                 \
@@ -8031,8 +8031,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 #define SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ)                        \
        do {                                                                  \
                int reg = BPF_REG_9;                                          \
-               BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) >                   \
-                            FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD));   \
+               BUILD_BUG_ON(sizeof_field(OBJ, OBJ_FIELD) >                   \
+                            sizeof_field(struct bpf_sock_ops, BPF_FIELD));   \
                if (si->dst_reg == reg || si->src_reg == reg)                 \
                        reg--;                                                \
                if (si->dst_reg == reg || si->src_reg == reg)                 \
@@ -8073,12 +8073,12 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        switch (si->off) {
        case offsetof(struct bpf_sock_ops, op) ...
             offsetof(struct bpf_sock_ops, replylong[3]):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, op) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, op));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, reply) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, reply));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, replylong) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, replylong));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, op) !=
+                            sizeof_field(struct bpf_sock_ops_kern, op));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, reply) !=
+                            sizeof_field(struct bpf_sock_ops_kern, reply));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, replylong) !=
+                            sizeof_field(struct bpf_sock_ops_kern, replylong));
                off = si->off;
                off -= offsetof(struct bpf_sock_ops, op);
                off += offsetof(struct bpf_sock_ops_kern, op);
@@ -8091,7 +8091,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                              struct bpf_sock_ops_kern, sk),
@@ -8102,7 +8102,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8113,7 +8113,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
@@ -8128,7 +8128,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct bpf_sock_ops, remote_ip6[0]) ...
             offsetof(struct bpf_sock_ops, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8149,7 +8149,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct bpf_sock_ops, local_ip6[0]) ...
             offsetof(struct bpf_sock_ops, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8168,7 +8168,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8182,7 +8182,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8202,7 +8202,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, state):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_state) != 1);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_state) != 1);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8213,7 +8213,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, rtt_min):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, rtt_min) !=
                             sizeof(struct minmax));
                BUILD_BUG_ON(sizeof(struct minmax) <
                             sizeof(struct minmax_sample));
@@ -8224,7 +8224,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct bpf_sock_ops_kern, sk));
                *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
                                      offsetof(struct tcp_sock, rtt_min) +
-                                     FIELD_SIZEOF(struct minmax_sample, t));
+                                     sizeof_field(struct minmax_sample, t));
                break;
 
        case offsetof(struct bpf_sock_ops, bpf_sock_ops_cb_flags):
@@ -8366,7 +8366,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct sk_msg, data_end));
                break;
        case offsetof(struct sk_msg_md, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                              struct sk_msg, sk),
@@ -8377,7 +8377,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8388,7 +8388,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
@@ -8403,7 +8403,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct sk_msg_md, remote_ip6[0]) ...
             offsetof(struct sk_msg_md, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8424,7 +8424,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct sk_msg_md, local_ip6[0]) ...
             offsetof(struct sk_msg_md, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8443,7 +8443,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8457,7 +8457,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8847,7 +8847,7 @@ sk_reuseport_is_valid_access(int off, int size,
 
        /* Fields that allow narrowing */
        case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
-               if (size < FIELD_SIZEOF(struct sk_buff, protocol))
+               if (size < sizeof_field(struct sk_buff, protocol))
                        return false;
                /* fall through */
        case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
@@ -8865,7 +8865,7 @@ sk_reuseport_is_valid_access(int off, int size,
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_reuseport_kern, F), \
                              si->dst_reg, si->src_reg,                 \
                              bpf_target_off(struct sk_reuseport_kern, F, \
-                                            FIELD_SIZEOF(struct sk_reuseport_kern, F), \
+                                            sizeof_field(struct sk_reuseport_kern, F), \
                                             target_size));             \
        })
 
index d524a69..2dbbb03 100644 (file)
@@ -599,8 +599,8 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
        offset += sizeof(struct gre_base_hdr);
 
        if (hdr->flags & GRE_CSUM)
-               offset += FIELD_SIZEOF(struct gre_full_hdr, csum) +
-                         FIELD_SIZEOF(struct gre_full_hdr, reserved1);
+               offset += sizeof_field(struct gre_full_hdr, csum) +
+                         sizeof_field(struct gre_full_hdr, reserved1);
 
        if (hdr->flags & GRE_KEY) {
                const __be32 *keyid;
@@ -622,11 +622,11 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
                        else
                                key_keyid->keyid = *keyid & GRE_PPTP_KEY_MASK;
                }
-               offset += FIELD_SIZEOF(struct gre_full_hdr, key);
+               offset += sizeof_field(struct gre_full_hdr, key);
        }
 
        if (hdr->flags & GRE_SEQ)
-               offset += FIELD_SIZEOF(struct pptp_gre_header, seq);
+               offset += sizeof_field(struct pptp_gre_header, seq);
 
        if (gre_ver == 0) {
                if (*p_proto == htons(ETH_P_TEB)) {
@@ -653,7 +653,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
                u8 *ppp_hdr;
 
                if (hdr->flags & GRE_ACK)
-                       offset += FIELD_SIZEOF(struct pptp_gre_header, ack);
+                       offset += sizeof_field(struct pptp_gre_header, ack);
 
                ppp_hdr = __skb_header_pointer(skb, *p_nhoff + offset,
                                               sizeof(_ppp_hdr),
index 7c8390a..8310714 100644 (file)
@@ -36,7 +36,7 @@ static u32 xdp_mem_id_hashfn(const void *data, u32 len, u32 seed)
        const u32 *k = data;
        const u32 key = *k;
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_mem_allocator, mem.id)
+       BUILD_BUG_ON(sizeof_field(struct xdp_mem_allocator, mem.id)
                     != sizeof(u32));
 
        /* Use cyclic increasing ID as direct hash key */
@@ -56,7 +56,7 @@ static const struct rhashtable_params mem_id_rht_params = {
        .nelem_hint = 64,
        .head_offset = offsetof(struct xdp_mem_allocator, node),
        .key_offset  = offsetof(struct xdp_mem_allocator, mem.id),
-       .key_len = FIELD_SIZEOF(struct xdp_mem_allocator, mem.id),
+       .key_len = sizeof_field(struct xdp_mem_allocator, mem.id),
        .max_size = MEM_ID_MAX,
        .min_size = 8,
        .automatic_shrinking = true,
index a52e8ba..4af8a98 100644 (file)
@@ -1132,7 +1132,7 @@ static int __init dccp_init(void)
        int rc;
 
        BUILD_BUG_ON(sizeof(struct dccp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        rc = percpu_counter_init(&dccp_orphan_count, 0, GFP_KERNEL);
        if (rc)
                goto out_fail;
index 572b630..8274f98 100644 (file)
@@ -1464,8 +1464,8 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
        [IFLA_GRE_OFLAGS]       = { .type = NLA_U16 },
        [IFLA_GRE_IKEY]         = { .type = NLA_U32 },
        [IFLA_GRE_OKEY]         = { .type = NLA_U32 },
-       [IFLA_GRE_LOCAL]        = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
-       [IFLA_GRE_REMOTE]       = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_GRE_LOCAL]        = { .len = sizeof_field(struct iphdr, saddr) },
+       [IFLA_GRE_REMOTE]       = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_GRE_TTL]          = { .type = NLA_U8 },
        [IFLA_GRE_TOS]          = { .type = NLA_U8 },
        [IFLA_GRE_PMTUDISC]     = { .type = NLA_U8 },
index cfb0256..9b153c7 100644 (file)
@@ -580,8 +580,8 @@ static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = {
        [IFLA_VTI_LINK]         = { .type = NLA_U32 },
        [IFLA_VTI_IKEY]         = { .type = NLA_U32 },
        [IFLA_VTI_OKEY]         = { .type = NLA_U32 },
-       [IFLA_VTI_LOCAL]        = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
-       [IFLA_VTI_REMOTE]       = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_VTI_LOCAL]        = { .len = sizeof_field(struct iphdr, saddr) },
+       [IFLA_VTI_REMOTE]       = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_VTI_FWMARK]       = { .type = NLA_U32 },
 };
 
index 8a39ee7..3e50ac2 100644 (file)
@@ -3949,7 +3949,7 @@ void __init tcp_init(void)
 
        BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE);
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
 
        percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL);
        percpu_counter_init(&tcp_orphan_count, 0, GFP_KERNEL);
index 923034c..9d09652 100644 (file)
@@ -2170,8 +2170,8 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
        [IFLA_GRE_OFLAGS]      = { .type = NLA_U16 },
        [IFLA_GRE_IKEY]        = { .type = NLA_U32 },
        [IFLA_GRE_OKEY]        = { .type = NLA_U32 },
-       [IFLA_GRE_LOCAL]       = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) },
-       [IFLA_GRE_REMOTE]      = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) },
+       [IFLA_GRE_LOCAL]       = { .len = sizeof_field(struct ipv6hdr, saddr) },
+       [IFLA_GRE_REMOTE]      = { .len = sizeof_field(struct ipv6hdr, daddr) },
        [IFLA_GRE_TTL]         = { .type = NLA_U8 },
        [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 },
        [IFLA_GRE_FLOWINFO]    = { .type = NLA_U32 },
index ebb62a4..c4bdcbc 100644 (file)
@@ -50,7 +50,7 @@ static struct iucv_interface *pr_iucv;
 static const u8 iprm_shutdown[8] =
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
 
-#define TRGCLS_SIZE    FIELD_SIZEOF(struct iucv_message, class)
+#define TRGCLS_SIZE    sizeof_field(struct iucv_message, class)
 
 #define __iucv_sock_wait(sk, condition, timeo, ret)                    \
 do {                                                                   \
index 062b73a..c26a566 100644 (file)
@@ -7595,7 +7595,7 @@ int nft_validate_register_load(enum nft_registers reg, unsigned int len)
                return -EINVAL;
        if (len == 0)
                return -EINVAL;
-       if (reg * NFT_REG32_SIZE + len > FIELD_SIZEOF(struct nft_regs, data))
+       if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data))
                return -ERANGE;
 
        return 0;
@@ -7643,7 +7643,7 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
                if (len == 0)
                        return -EINVAL;
                if (reg * NFT_REG32_SIZE + len >
-                   FIELD_SIZEOF(struct nft_regs, data))
+                   sizeof_field(struct nft_regs, data))
                        return -ERANGE;
 
                if (data != NULL && type != NFT_DATA_VALUE)
index 7525063..de3a959 100644 (file)
@@ -236,7 +236,7 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
        nla_strlcpy(helper->name,
                    tb[NFCTH_NAME], NF_CT_HELPER_NAME_LEN);
        size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
-       if (size > FIELD_SIZEOF(struct nf_conn_help, data)) {
+       if (size > sizeof_field(struct nf_conn_help, data)) {
                ret = -ENOMEM;
                goto err2;
        }
index 46ca8bc..faea72c 100644 (file)
@@ -440,12 +440,12 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
 
                switch (ctx->family) {
                case NFPROTO_IPV4:
-                       len = FIELD_SIZEOF(struct nf_conntrack_tuple,
+                       len = sizeof_field(struct nf_conntrack_tuple,
                                           src.u3.ip);
                        break;
                case NFPROTO_IPV6:
                case NFPROTO_INET:
-                       len = FIELD_SIZEOF(struct nf_conntrack_tuple,
+                       len = sizeof_field(struct nf_conntrack_tuple,
                                           src.u3.ip6);
                        break;
                default:
@@ -457,20 +457,20 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
 
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip);
                break;
        case NFT_CT_SRC_IP6:
        case NFT_CT_DST_IP6:
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
 
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip6);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip6);
                break;
        case NFT_CT_PROTO_SRC:
        case NFT_CT_PROTO_DST:
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u.all);
                break;
        case NFT_CT_BYTES:
        case NFT_CT_PKTS:
@@ -551,7 +551,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
        case NFT_CT_MARK:
                if (tb[NFTA_CT_DIRECTION])
                        return -EINVAL;
-               len = FIELD_SIZEOF(struct nf_conn, mark);
+               len = sizeof_field(struct nf_conn, mark);
                break;
 #endif
 #ifdef CONFIG_NF_CONNTRACK_LABELS
index 39dc94f..bc9fd98 100644 (file)
@@ -43,7 +43,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
                         const struct nft_expr *expr,
                         const struct nlattr * const tb[])
 {
-       u32 plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       u32 plen = sizeof_field(struct nf_nat_range, min_addr.all);
        struct nft_masq *priv = nft_expr_priv(expr);
        int err;
 
index c3c93e9..8b44a4d 100644 (file)
@@ -141,10 +141,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 
        switch (family) {
        case NFPROTO_IPV4:
-               alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip);
+               alen = sizeof_field(struct nf_nat_range, min_addr.ip);
                break;
        case NFPROTO_IPV6:
-               alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip6);
+               alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
                break;
        default:
                return -EAFNOSUPPORT;
@@ -171,7 +171,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                }
        }
 
-       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_addr.all);
        if (tb[NFTA_NAT_REG_PROTO_MIN]) {
                priv->sreg_proto_min =
                        nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]);
index 43eeb1f..5b77917 100644 (file)
@@ -48,7 +48,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
        unsigned int plen;
        int err;
 
-       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_addr.all);
        if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
                priv->sreg_proto_min =
                        nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]);
index f92a82c..4c33dfc 100644 (file)
@@ -218,14 +218,14 @@ static int nft_tproxy_init(const struct nft_ctx *ctx,
 
        switch (priv->family) {
        case NFPROTO_IPV4:
-               alen = FIELD_SIZEOF(union nf_inet_addr, in);
+               alen = sizeof_field(union nf_inet_addr, in);
                err = nf_defrag_ipv4_enable(ctx->net);
                if (err)
                        return err;
                break;
 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
        case NFPROTO_IPV6:
-               alen = FIELD_SIZEOF(union nf_inet_addr, in6);
+               alen = sizeof_field(union nf_inet_addr, in6);
                err = nf_defrag_ipv6_enable(ctx->net);
                if (err)
                        return err;
index 2236455..37253d3 100644 (file)
@@ -30,7 +30,7 @@ static unsigned int jhash_rnd __read_mostly;
 
 static unsigned int xt_rateest_hash(const char *name)
 {
-       return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) &
+       return jhash(name, sizeof_field(struct xt_rateest, name), jhash_rnd) &
               (RATEEST_HSIZE - 1);
 }
 
index 90b2ab9..4e31721 100644 (file)
@@ -2755,7 +2755,7 @@ static int __init netlink_proto_init(void)
        if (err != 0)
                goto out;
 
-       BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof_field(struct sk_buff, cb));
 
        nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
        if (!nl_table)
index 1047e80..e3a37d2 100644 (file)
@@ -2497,7 +2497,7 @@ static int __init dp_init(void)
 {
        int err;
 
-       BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > sizeof_field(struct sk_buff, cb));
 
        pr_info("Open vSwitch switching datapath\n");
 
index fd8ed76..758a8c7 100644 (file)
@@ -37,7 +37,7 @@ enum sw_flow_mac_proto {
  * matching for small options.
  */
 #define TUN_METADATA_OFFSET(opt_len) \
-       (FIELD_SIZEOF(struct sw_flow_key, tun_opts) - opt_len)
+       (sizeof_field(struct sw_flow_key, tun_opts) - opt_len)
 #define TUN_METADATA_OPTS(flow_key, opt_len) \
        ((void *)((flow_key)->tun_opts + TUN_METADATA_OFFSET(opt_len)))
 
@@ -52,7 +52,7 @@ struct vlan_head {
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE                  \
        (offsetof(struct sw_flow_key, recirc_id) +      \
-       FIELD_SIZEOF(struct sw_flow_key, recirc_id))
+       sizeof_field(struct sw_flow_key, recirc_id))
 
 struct ovs_key_nsh {
        struct ovs_nsh_key_base base;
index d72ddb6..9d3c4d2 100644 (file)
@@ -972,7 +972,7 @@ static int __init af_rxrpc_init(void)
        int ret = -1;
        unsigned int tmp;
 
-       BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
 
        get_random_bytes(&tmp, sizeof(tmp));
        tmp &= 0x3fffffff;
index bf2d693..f685c0d 100644 (file)
@@ -312,7 +312,7 @@ static void tcf_ct_act_set_labels(struct nf_conn *ct,
                                  u32 *labels_m)
 {
 #if IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS)
-       size_t labels_sz = FIELD_SIZEOF(struct tcf_ct_params, labels);
+       size_t labels_sz = sizeof_field(struct tcf_ct_params, labels);
 
        if (!memchr_inv(labels_m, 0, labels_sz))
                return;
@@ -936,7 +936,7 @@ static struct tc_action_ops act_ct_ops = {
 
 static __net_init int ct_init_net(struct net *net)
 {
-       unsigned int n_bits = FIELD_SIZEOF(struct tcf_ct_params, labels) * 8;
+       unsigned int n_bits = sizeof_field(struct tcf_ct_params, labels) * 8;
        struct tc_ct_action_net *tn = net_generic(net, ct_net_id);
 
        if (nf_connlabels_get(net, n_bits - 1)) {
index 6c68971..0d125de 100644 (file)
@@ -1481,7 +1481,7 @@ static int fl_init_mask_hashtable(struct fl_flow_mask *mask)
 }
 
 #define FL_KEY_MEMBER_OFFSET(member) offsetof(struct fl_flow_key, member)
-#define FL_KEY_MEMBER_SIZE(member) FIELD_SIZEOF(struct fl_flow_key, member)
+#define FL_KEY_MEMBER_SIZE(member) sizeof_field(struct fl_flow_key, member)
 
 #define FL_KEY_IS_MASKED(mask, member)                                         \
        memchr_inv(((char *)mask) + FL_KEY_MEMBER_OFFSET(member),               \
index 4d38d49..5062321 100644 (file)
@@ -957,7 +957,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
                             .msg_iocb = iocb};
        ssize_t res;
 
-       if (file->f_flags & O_NONBLOCK)
+       if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
                msg.msg_flags = MSG_DONTWAIT;
 
        if (iocb->ki_pos != 0)
@@ -982,7 +982,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (iocb->ki_pos != 0)
                return -ESPIPE;
 
-       if (file->f_flags & O_NONBLOCK)
+       if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
                msg.msg_flags = MSG_DONTWAIT;
 
        if (sock->type == SOCK_SEQPACKET)
index 7cfdce1..774babb 100644 (file)
@@ -2865,7 +2865,7 @@ static int __init af_unix_init(void)
 {
        int rc = -1;
 
-       BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb));
 
        rc = proto_register(&unix_proto, 1);
        if (rc != 0) {
index 7cbe6e7..a63380c 100755 (executable)
@@ -4125,15 +4125,6 @@ sub process {
                             "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
                }
 
-               if ($line =~ /\bpr_warning\s*\(/) {
-                       if (WARN("PREFER_PR_LEVEL",
-                                "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
-                           $fix) {
-                               $fixed[$fixlinenr] =~
-                                   s/\bpr_warning\b/pr_warn/;
-                       }
-               }
-
                if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
                        my $orig = $1;
                        my $level = lc($orig);
index f19a895..ef8dfd4 100644 (file)
@@ -45,7 +45,7 @@
 #define DONT_HASH      0x0200
 
 #define INVALID_PCR(a) (((a) < 0) || \
-       (a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))
+       (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))
 
 int ima_policy_flag;
 static int temp_ima_appraise;
@@ -274,7 +274,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
         * lsm rules can change
         */
        memcpy(nentry, entry, sizeof(*nentry));
-       memset(nentry->lsm, 0, FIELD_SIZEOF(struct ima_rule_entry, lsm));
+       memset(nentry->lsm, 0, sizeof_field(struct ima_rule_entry, lsm));
 
        for (i = 0; i < MAX_LSM_RULES; i++) {
                if (!entry->lsm[i].rule)
index dd31343..47c0415 100644 (file)
@@ -21,10 +21,6 @@ config KEYS
 
          If you are unsure as to whether this is required, answer N.
 
-config KEYS_COMPAT
-       def_bool y
-       depends on COMPAT && KEYS
-
 config KEYS_REQUEST_CACHE
        bool "Enable temporary caching of the last request_key() result"
        depends on KEYS
index 074f275..5f40807 100644 (file)
@@ -17,7 +17,7 @@ obj-y := \
        request_key_auth.o \
        user_defined.o
 compat-obj-$(CONFIG_KEY_DH_OPERATIONS) += compat_dh.o
-obj-$(CONFIG_KEYS_COMPAT) += compat.o $(compat-obj-y)
+obj-$(CONFIG_COMPAT) += compat.o $(compat-obj-y)
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
 obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
index 9bcc404..b975f8f 100644 (file)
@@ -46,11 +46,6 @@ static long compat_keyctl_instantiate_key_iov(
 
 /*
  * The key control system call, 32-bit compatibility version for 64-bit archs
- *
- * This should only be called if the 64-bit arch uses weird pointers in 32-bit
- * mode or doesn't guarantee that the top 32-bits of the argument registers on
- * taking a 32-bit syscall are zero.  If you can, you should call sys_keyctl()
- * directly.
  */
 COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
                       u32, arg2, u32, arg3, u32, arg4, u32, arg5)
index c039373..ba3e2da 100644 (file)
@@ -264,7 +264,7 @@ extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
                              size_t, struct keyctl_kdf_params __user *);
 extern long __keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
                                size_t, struct keyctl_kdf_params *);
-#ifdef CONFIG_KEYS_COMPAT
+#ifdef CONFIG_COMPAT
 extern long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params,
                                char __user *buffer, size_t buflen,
                                struct compat_keyctl_kdf_params __user *kdf);
@@ -279,7 +279,7 @@ static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params,
        return -EOPNOTSUPP;
 }
 
-#ifdef CONFIG_KEYS_COMPAT
+#ifdef CONFIG_COMPAT
 static inline long compat_keyctl_dh_compute(
                                struct keyctl_dh_params __user *params,
                                char __user *buffer, size_t buflen,
index a9810ac..08ec7f4 100644 (file)
@@ -309,6 +309,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
                return rc;
 
        rc = tpm2_unseal_cmd(chip, payload, options, blob_handle);
+       tpm2_flush_context(chip, blob_handle);
 
        return rc;
 }
index 1fe5811..d083225 100644 (file)
@@ -739,6 +739,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
                runtime->boundary *= 2;
 
+       /* clear the buffer for avoiding possible kernel info leaks */
+       if (runtime->dma_area && !substream->ops->copy_user)
+               memset(runtime->dma_area, 0, runtime->dma_bytes);
+
        snd_pcm_timer_resolution_change(substream);
        snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
index 4e3bd9a..bd91c6e 100644 (file)
@@ -247,7 +247,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                mutex_unlock(&ff->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 static int pcm_hw_free(struct snd_pcm_substream *substream)
index 349b4d0..0059709 100644 (file)
@@ -177,18 +177,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
                                        SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
                                        frames_per_period, frames_per_period);
-                       if (err < 0) {
-                               mutex_unlock(&motu->mutex);
+                       if (err < 0)
                                goto err_locked;
-                       }
 
                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
                                        SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
                                        frames_per_buffer, frames_per_buffer);
-                       if (err < 0) {
-                               mutex_unlock(&motu->mutex);
+                       if (err < 0)
                                goto err_locked;
-                       }
                }
        }
 
index 9124603..67fd3e8 100644 (file)
@@ -285,7 +285,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                mutex_unlock(&oxfw->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
index f9707fb..682ed39 100644 (file)
@@ -120,10 +120,8 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
        snd_hdac_stream_updateb(azx_dev, SD_CTL,
                                SD_CTL_DMA_START | SD_INT_MASK, 0);
        snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
-       if (azx_dev->stripe) {
+       if (azx_dev->stripe)
                snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
-               azx_dev->stripe = 0;
-       }
        azx_dev->running = false;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
index 50d4a87..f02f5b1 100644 (file)
@@ -635,36 +635,30 @@ This function assumes there are no more than 16 in/out busses or pipes
 Meters is an array [3][16][2] of long. */
 static void get_audio_meters(struct echoaudio *chip, long *meters)
 {
-       int i, m, n;
+       unsigned int i, m, n;
 
-       m = 0;
-       n = 0;
-       for (i = 0; i < num_busses_out(chip); i++, m++) {
+       for (i = 0 ; i < 96; i++)
+               meters[i] = 0;
+
+       for (m = 0, n = 0, i = 0; i < num_busses_out(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
-       for (; n < 32; n++)
-               meters[n] = 0;
 
 #ifdef ECHOCARD_ECHO3G
        m = E3G_MAX_OUTPUTS;    /* Skip unused meters */
 #endif
 
-       for (i = 0; i < num_busses_in(chip); i++, m++) {
+       for (n = 32, i = 0; i < num_busses_in(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
-       for (; n < 64; n++)
-               meters[n] = 0;
-
 #ifdef ECHOCARD_HAS_VMIXER
-       for (i = 0; i < num_pipes_out(chip); i++, m++) {
+       for (n = 64, i = 0; i < num_pipes_out(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
 #endif
-       for (; n < 96; n++)
-               meters[n] = 0;
 }
 
 
index 2f3b7a3..ba56b59 100644 (file)
@@ -883,7 +883,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
                return -EAGAIN; /* give a chance to retry */
        }
 
-       dev_WARN(chip->card->dev,
+       dev_err(chip->card->dev,
                "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n",
                bus->last_cmd[addr]);
        chip->single_cmd = 1;
index 35b4526..b856b89 100644 (file)
@@ -1419,7 +1419,6 @@ static bool atpx_present(void)
                                return true;
                        }
                }
-               pci_dev_put(pdev);
        }
        return false;
 }
index b7a1abb..32ed464 100644 (file)
@@ -1809,13 +1809,14 @@ struct scp_msg {
 
 static void dspio_clear_response_queue(struct hda_codec *codec)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        unsigned int dummy = 0;
-       int status = -1;
+       int status;
 
        /* clear all from the response queue */
        do {
                status = dspio_read(codec, &dummy);
-       } while (status == 0);
+       } while (status == 0 && time_before(jiffies, timeout));
 }
 
 static int dspio_get_response_data(struct hda_codec *codec)
@@ -7588,12 +7589,14 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
        struct ca0132_spec *spec = codec->spec;
 
        codec_dbg(codec, "ca0132_process_dsp_response\n");
+       snd_hda_power_up_pm(codec);
        if (spec->wait_scp) {
                if (dspio_get_response_data(codec) >= 0)
                        spec->wait_scp = 0;
        }
 
        dspio_clear_response_queue(codec);
+       snd_hda_power_down_pm(codec);
 }
 
 static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -7604,11 +7607,10 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
        /* Delay enabling the HP amp, to let the mic-detection
         * state machine run.
         */
-       cancel_delayed_work(&spec->unsol_hp_work);
-       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
        tbl = snd_hda_jack_tbl_get(codec, cb->nid);
        if (tbl)
                tbl->block_report = 1;
+       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
 }
 
 static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -8454,12 +8456,25 @@ static void ca0132_reboot_notify(struct hda_codec *codec)
        codec->patch_ops.free(codec);
 }
 
+#ifdef CONFIG_PM
+static int ca0132_suspend(struct hda_codec *codec)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       cancel_delayed_work_sync(&spec->unsol_hp_work);
+       return 0;
+}
+#endif
+
 static const struct hda_codec_ops ca0132_patch_ops = {
        .build_controls = ca0132_build_controls,
        .build_pcms = ca0132_build_pcms,
        .init = ca0132_init,
        .free = ca0132_free,
        .unsol_event = snd_hda_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = ca0132_suspend,
+#endif
        .reboot_notify = ca0132_reboot_notify,
 };
 
index 78647ee..630b1f5 100644 (file)
@@ -2021,6 +2021,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
                per_cvt->assigned = 0;
                hinfo->nid = 0;
 
+               azx_stream(get_azx_dev(substream))->stripe = 0;
+
                mutex_lock(&spec->pcm_lock);
                snd_hda_spdif_ctls_unassign(codec, pcm_idx);
                clear_bit(pcm_idx, &spec->pcm_in_use);
index 6d6e34b..dbfafee 100644 (file)
@@ -7643,11 +7643,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x1a, 0x90a70130},
                {0x1b, 0x90170110},
                {0x21, 0x03211020}),
-       SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
-               {0x12, 0xb7a60130},
-               {0x13, 0xb8a61140},
-               {0x16, 0x90170110},
-               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
                {0x12, 0x90a60130},
                {0x14, 0x90170110},
@@ -7841,6 +7836,9 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
        SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x19, 0x40000000},
                {0x1a, 0x40000000}),
+       SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
+               {0x19, 0x40000000},
+               {0x1a, 0x40000000}),
        {}
 };
 
index f4ee679..7a5621e 100644 (file)
@@ -96,14 +96,19 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static int da7219_clk_enable(struct snd_pcm_substream *substream,
-                            int wclk_rate, int bclk_rate)
+static int da7219_clk_enable(struct snd_pcm_substream *substream)
 {
        int ret = 0;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 
-       clk_set_rate(da7219_dai_wclk, wclk_rate);
-       clk_set_rate(da7219_dai_bclk, bclk_rate);
+       /*
+        * Set wclk to 48000 because the rate constraint of this driver is
+        * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is
+        * minimum of 64x the LRCLK sample rate." DA7219 is the only clk
+        * source so for all codecs we have to limit bclk to 64X lrclk.
+        */
+       clk_set_rate(da7219_dai_wclk, 48000);
+       clk_set_rate(da7219_dai_bclk, 48000 * 64);
        ret = clk_prepare_enable(da7219_dai_bclk);
        if (ret < 0) {
                dev_err(rtd->dev, "can't enable master clock %d\n", ret);
@@ -156,7 +161,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
                                   &constraints_rates);
 
        machine->play_i2s_instance = I2S_SP_INSTANCE;
-       return 0;
+       return da7219_clk_enable(substream);
 }
 
 static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
@@ -178,7 +183,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
 
        machine->cap_i2s_instance = I2S_SP_INSTANCE;
        machine->capture_channel = CAP_CHANNEL1;
-       return 0;
+       return da7219_clk_enable(substream);
 }
 
 static int cz_max_startup(struct snd_pcm_substream *substream)
@@ -199,7 +204,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
                                   &constraints_rates);
 
        machine->play_i2s_instance = I2S_BT_INSTANCE;
-       return 0;
+       return da7219_clk_enable(substream);
 }
 
 static int cz_dmic0_startup(struct snd_pcm_substream *substream)
@@ -220,7 +225,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
                                   &constraints_rates);
 
        machine->cap_i2s_instance = I2S_BT_INSTANCE;
-       return 0;
+       return da7219_clk_enable(substream);
 }
 
 static int cz_dmic1_startup(struct snd_pcm_substream *substream)
@@ -242,25 +247,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream *substream)
 
        machine->cap_i2s_instance = I2S_SP_INSTANCE;
        machine->capture_channel = CAP_CHANNEL0;
-       return 0;
-}
-
-static int cz_da7219_params(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *params)
-{
-       int wclk, bclk;
-
-       wclk = params_rate(params);
-       bclk = wclk * params_channels(params) *
-               snd_pcm_format_width(params_format(params));
-       /* ADAU7002 spec: "The ADAU7002 requires a BCLK rate
-        * that is minimum of 64x the LRCLK sample rate."
-        * DA7219 is the only clk source so for all codecs
-        * we have to limit bclk to 64X lrclk.
-        */
-       if (bclk < (wclk * 64))
-               bclk = wclk * 64;
-       return da7219_clk_enable(substream, wclk, bclk);
+       return da7219_clk_enable(substream);
 }
 
 static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
@@ -271,31 +258,26 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
 static const struct snd_soc_ops cz_da7219_play_ops = {
        .startup = cz_da7219_play_startup,
        .shutdown = cz_da7219_shutdown,
-       .hw_params = cz_da7219_params,
 };
 
 static const struct snd_soc_ops cz_da7219_cap_ops = {
        .startup = cz_da7219_cap_startup,
        .shutdown = cz_da7219_shutdown,
-       .hw_params = cz_da7219_params,
 };
 
 static const struct snd_soc_ops cz_max_play_ops = {
        .startup = cz_max_startup,
        .shutdown = cz_da7219_shutdown,
-       .hw_params = cz_da7219_params,
 };
 
 static const struct snd_soc_ops cz_dmic0_cap_ops = {
        .startup = cz_dmic0_startup,
        .shutdown = cz_da7219_shutdown,
-       .hw_params = cz_da7219_params,
 };
 
 static const struct snd_soc_ops cz_dmic1_cap_ops = {
        .startup = cz_dmic1_startup,
        .shutdown = cz_da7219_shutdown,
-       .hw_params = cz_da7219_params,
 };
 
 SND_SOC_DAILINK_DEF(designware1,
index f8b5b96..4eaa2b5 100644 (file)
@@ -292,7 +292,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-       uinfo->count = FIELD_SIZEOF(struct hdmi_codec_priv, eld);
+       uinfo->count = sizeof_field(struct hdmi_codec_priv, eld);
 
        return 0;
 }
index f6bf4cf..e46b6ad 100644 (file)
@@ -2103,26 +2103,40 @@ static void max98090_pll_det_disable_work(struct work_struct *work)
                            M98090_IULK_MASK, 0);
 }
 
-static void max98090_pll_work(struct work_struct *work)
+static void max98090_pll_work(struct max98090_priv *max98090)
 {
-       struct max98090_priv *max98090 =
-               container_of(work, struct max98090_priv, pll_work);
        struct snd_soc_component *component = max98090->component;
+       unsigned int pll;
+       int i;
 
        if (!snd_soc_component_is_active(component))
                return;
 
        dev_info_ratelimited(component->dev, "PLL unlocked\n");
 
+       /*
+        * As the datasheet suggested, the maximum PLL lock time should be
+        * 7 msec.  The workaround resets the codec softly by toggling SHDN
+        * off and on if PLL failed to lock for 10 msec.  Notably, there is
+        * no suggested hold time for SHDN off.
+        */
+
        /* Toggle shutdown OFF then ON */
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, 0);
-       msleep(10);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, M98090_SHDNN_MASK);
 
-       /* Give PLL time to lock */
-       msleep(10);
+       for (i = 0; i < 10; ++i) {
+               /* Give PLL time to lock */
+               usleep_range(1000, 1200);
+
+               /* Check lock status */
+               pll = snd_soc_component_read32(
+                               component, M98090_REG_DEVICE_STATUS);
+               if (!(pll & M98090_ULK_MASK))
+                       break;
+       }
 }
 
 static void max98090_jack_work(struct work_struct *work)
@@ -2259,7 +2273,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
 
        if (active & M98090_ULK_MASK) {
                dev_dbg(component->dev, "M98090_ULK_MASK\n");
-               schedule_work(&max98090->pll_work);
+               max98090_pll_work(max98090);
        }
 
        if (active & M98090_JDET_MASK) {
@@ -2422,7 +2436,6 @@ static int max98090_probe(struct snd_soc_component *component)
                          max98090_pll_det_enable_work);
        INIT_WORK(&max98090->pll_det_disable_work,
                  max98090_pll_det_disable_work);
-       INIT_WORK(&max98090->pll_work, max98090_pll_work);
 
        /* Enable jack detection */
        snd_soc_component_write(component, M98090_REG_JACK_DETECT,
@@ -2475,7 +2488,6 @@ static void max98090_remove(struct snd_soc_component *component)
        cancel_delayed_work_sync(&max98090->jack_work);
        cancel_delayed_work_sync(&max98090->pll_det_enable_work);
        cancel_work_sync(&max98090->pll_det_disable_work);
-       cancel_work_sync(&max98090->pll_work);
        max98090->component = NULL;
 }
 
index 57965cd..a197114 100644 (file)
@@ -1530,7 +1530,6 @@ struct max98090_priv {
        struct delayed_work jack_work;
        struct delayed_work pll_det_enable_work;
        struct work_struct pll_det_disable_work;
-       struct work_struct pll_work;
        struct snd_soc_jack *jack;
        unsigned int dai_fmt;
        int tdm_slots;
index 3af36ec..088b779 100644 (file)
@@ -9,9 +9,25 @@
 #ifndef __RT5677_SPI_H__
 #define __RT5677_SPI_H__
 
+#if IS_ENABLED(CONFIG_SND_SOC_RT5677_SPI)
 int rt5677_spi_read(u32 addr, void *rxbuf, size_t len);
 int rt5677_spi_write(u32 addr, const void *txbuf, size_t len);
 int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw);
 void rt5677_spi_hotword_detected(void);
+#else
+static inline int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
+{
+       return -EINVAL;
+}
+static inline int rt5677_spi_write(u32 addr, const void *txbuf, size_t len)
+{
+       return -EINVAL;
+}
+static inline int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw)
+{
+       return -EINVAL;
+}
+static inline void rt5677_spi_hotword_detected(void){}
+#endif
 
 #endif /* __RT5677_SPI_H__ */
index b1713ff..ae6f612 100644 (file)
@@ -73,6 +73,7 @@ struct rt5682_priv {
 static const struct reg_sequence patch_list[] = {
        {RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
        {RT5682_DAC_ADC_DIG_VOL1, 0xa020},
+       {RT5682_I2C_CTRL, 0x000f},
 };
 
 static const struct reg_default rt5682_reg[] = {
@@ -2474,6 +2475,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
        mutex_lock(&rt5682->calibrate_mutex);
 
        rt5682_reset(rt5682->regmap);
+       regmap_write(rt5682->regmap, RT5682_I2C_CTRL, 0x000f);
        regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af);
        usleep_range(15000, 20000);
        regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2af);
index 7d7ea15..5ffbadd 100644 (file)
@@ -1806,6 +1806,12 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 
        switch (clk_id) {
        case WM8904_CLK_AUTO:
+               /* We don't have any rate constraints, so just ignore the
+                * request to disable constraining.
+                */
+               if (!freq)
+                       return 0;
+
                mclk_freq = clk_get_rate(priv->mclk);
                /* enable FLL if a different sysclk is desired */
                if (mclk_freq != freq) {
index 3e5c69f..d9d59f4 100644 (file)
@@ -2788,7 +2788,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
 
        if (target % Fref == 0) {
                fll_div->theta = 0;
-               fll_div->lambda = 0;
+               fll_div->lambda = 1;
        } else {
                gcd_fll = gcd(target, fratio * Fref);
 
@@ -2858,7 +2858,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
                return -EINVAL;
        }
 
-       if (fll_div.theta || fll_div.lambda)
+       if (fll_div.theta)
                fll1 |= WM8962_FLL_FRAC;
 
        /* Stop the FLL while we reconfigure */
index 10b82bf..55e9f88 100644 (file)
@@ -371,6 +371,7 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
        do {
                struct asoc_simple_data adata;
                struct device_node *codec;
+               struct device_node *plat;
                struct device_node *np;
                int num = of_get_child_count(node);
 
@@ -381,6 +382,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
                        ret = -ENODEV;
                        goto error;
                }
+               /* get platform */
+               plat = of_get_child_by_name(node, is_top ?
+                                           PREFIX "plat" : "plat");
 
                /* get convert-xxx property */
                memset(&adata, 0, sizeof(adata));
@@ -389,6 +393,8 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
 
                /* loop for all CPU/Codec node */
                for_each_child_of_node(node, np) {
+                       if (plat == np)
+                               continue;
                        /*
                         * It is DPCM
                         * if it has many CPUs,
index fbecbb7..68bcec5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/firmware.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_qos.h>
index dd2b5ad..243f683 100644 (file)
@@ -707,13 +707,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_MCLK_EN),
        },
        {
+               /* Teclast X89 */
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
                        DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
                },
                .driver_data = (void *)(BYT_RT5640_IN3_MAP |
-                                       BYT_RT5640_MCLK_EN |
-                                       BYT_RT5640_SSP0_AIF1),
+                                       BYT_RT5640_JD_SRC_JD1_IN4P |
+                                       BYT_RT5640_OVCD_TH_2000UA |
+                                       BYT_RT5640_OVCD_SF_1P0 |
+                                       BYT_RT5640_SSP0_AIF1 |
+                                       BYT_RT5640_MCLK_EN),
        },
        {       /* Toshiba Satellite Click Mini L9W-B */
                .matches = {
index 5d08ae0..fb9ba88 100644 (file)
@@ -9,45 +9,52 @@
 #include <sound/soc-acpi.h>
 #include <sound/soc-acpi-intel-match.h>
 
-static struct snd_soc_acpi_codecs cml_codecs = {
+static struct snd_soc_acpi_codecs rt1011_spk_codecs = {
        .num_codecs = 1,
-       .codecs = {"10EC5682"}
+       .codecs = {"10EC1011"}
 };
 
-static struct snd_soc_acpi_codecs cml_spk_codecs = {
+static struct snd_soc_acpi_codecs max98357a_spk_codecs = {
        .num_codecs = 1,
        .codecs = {"MX98357A"}
 };
 
+/*
+ * The order of the three entries with .id = "10EC5682" matters
+ * here, because DSDT tables expose an ACPI HID for the MAX98357A
+ * speaker amplifier which is not populated on the board.
+ */
 struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
        {
-               .id = "DLGS7219",
-               .drv_name = "cml_da7219_max98357a",
-               .quirk_data = &cml_spk_codecs,
+               .id = "10EC5682",
+               .drv_name = "cml_rt1011_rt5682",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &rt1011_spk_codecs,
                .sof_fw_filename = "sof-cml.ri",
-               .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg",
+               .sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg",
        },
        {
-               .id = "MX98357A",
+               .id = "10EC5682",
                .drv_name = "sof_rt5682",
-               .quirk_data = &cml_codecs,
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &max98357a_spk_codecs,
                .sof_fw_filename = "sof-cml.ri",
                .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg",
        },
        {
-               .id = "10EC1011",
-               .drv_name = "cml_rt1011_rt5682",
-               .quirk_data = &cml_codecs,
-               .sof_fw_filename = "sof-cml.ri",
-               .sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg",
-       },
-       {
                .id = "10EC5682",
                .drv_name = "sof_rt5682",
                .sof_fw_filename = "sof-cml.ri",
                .sof_tplg_filename = "sof-cml-rt5682.tplg",
        },
-
+       {
+               .id = "DLGS7219",
+               .drv_name = "cml_da7219_max98357a",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &max98357a_spk_codecs,
+               .sof_fw_filename = "sof-cml.ri",
+               .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg",
+       },
        {},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
index 61f2303..6615ef6 100644 (file)
@@ -214,10 +214,8 @@ be_err:
  * This is to ensure there are no pops or clicks in between any music tracks
  * due to DAPM power cycling.
  */
-static void close_delayed_work(struct work_struct *work)
+static void close_delayed_work(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_pcm_runtime *rtd =
-                       container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
@@ -929,7 +927,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
        }
 
        /* DAPM dai link stream work */
-       INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+       rtd->close_delayed_work_func = close_delayed_work;
 
        rtd->compr = compr;
        compr->private_data = rtd;
index 062653a..1c84ff1 100644 (file)
@@ -419,7 +419,8 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
 
        list_del(&rtd->list);
 
-       flush_delayed_work(&rtd->delayed_work);
+       if (delayed_work_pending(&rtd->delayed_work))
+               flush_delayed_work(&rtd->delayed_work);
        snd_soc_pcm_component_free(rtd);
 
        /*
@@ -435,6 +436,15 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
        device_unregister(rtd->dev);
 }
 
+static void close_delayed_work(struct work_struct *work) {
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(work, struct snd_soc_pcm_runtime,
+                                    delayed_work.work);
+
+       if (rtd->close_delayed_work_func)
+               rtd->close_delayed_work_func(rtd);
+}
+
 static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
        struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
 {
@@ -470,6 +480,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
 
        rtd->dev = dev;
        dev_set_drvdata(dev, rtd);
+       INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
 
        /*
         * for rtd->codec_dais
index 76b7ee6..01e7bc0 100644 (file)
@@ -637,10 +637,8 @@ out:
  * This is to ensure there are no pops or clicks in between any music tracks
  * due to DAPM power cycling.
  */
-static void close_delayed_work(struct work_struct *work)
+static void close_delayed_work(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_pcm_runtime *rtd =
-                       container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
        struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
 
        mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
@@ -660,7 +658,7 @@ static void close_delayed_work(struct work_struct *work)
        mutex_unlock(&rtd->card->pcm_mutex);
 }
 
-static void codec2codec_close_delayed_work(struct work_struct *work)
+static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
 {
        /*
         * Currently nothing to do for c2c links
@@ -2974,10 +2972,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
        /* DAPM dai link stream work */
        if (rtd->dai_link->params)
-               INIT_DELAYED_WORK(&rtd->delayed_work,
-                                 codec2codec_close_delayed_work);
+               rtd->close_delayed_work_func = codec2codec_close_delayed_work;
        else
-               INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+               rtd->close_delayed_work_func = close_delayed_work;
 
        pcm->nonatomic = rtd->dai_link->nonatomic;
        rtd->pcm = pcm;
index 81d2af0..b286131 100644 (file)
@@ -1933,11 +1933,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
        ret = soc_tplg_dai_link_load(tplg, link, NULL);
        if (ret < 0) {
                dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
-               kfree(link->name);
-               kfree(link->stream_name);
-               kfree(link->cpus->dai_name);
-               kfree(link);
-               return ret;
+               goto err;
+       }
+
+       ret = snd_soc_add_dai_link(tplg->comp->card, link);
+       if (ret < 0) {
+               dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n");
+               goto err;
        }
 
        link->dobj.index = tplg->index;
@@ -1945,8 +1947,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
        link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
        list_add(&link->dobj.list, &tplg->comp->dobj_list);
 
-       snd_soc_add_dai_link(tplg->comp->card, link);
        return 0;
+err:
+       kfree(link->name);
+       kfree(link->stream_name);
+       kfree(link->cpus->dai_name);
+       kfree(link);
+       return ret;
 }
 
 /* create a FE DAI and DAI link from the PCM object */
@@ -2039,6 +2046,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
        int size;
        int i;
        bool abi_match;
+       int ret;
 
        count = le32_to_cpu(hdr->count);
 
@@ -2080,7 +2088,12 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
                }
 
                /* create the FE DAIs and DAI links */
-               soc_tplg_pcm_create(tplg, _pcm);
+               ret = soc_tplg_pcm_create(tplg, _pcm);
+               if (ret < 0) {
+                       if (!abi_match)
+                               kfree(_pcm);
+                       return ret;
+               }
 
                /* offset by version-specific struct size and
                 * real priv data size
index 2abf80b..92ef6a7 100644 (file)
@@ -24,7 +24,8 @@
 #define DRAM_OFFSET            0x100000
 #define DRAM_SIZE              (160 * 1024)
 #define SHIM_OFFSET            0x140000
-#define SHIM_SIZE              0x100
+#define SHIM_SIZE_BYT          0x100
+#define SHIM_SIZE_CHT          0x118
 #define MBOX_OFFSET            0x144000
 #define MBOX_SIZE              0x1000
 #define EXCEPT_OFFSET          0x800
@@ -75,7 +76,7 @@ static const struct snd_sof_debugfs_map byt_debugfs[] = {
         SOF_DEBUGFS_ACCESS_D0_ONLY},
        {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
         SOF_DEBUGFS_ACCESS_D0_ONLY},
-       {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
+       {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
         SOF_DEBUGFS_ACCESS_ALWAYS},
 };
 
@@ -102,7 +103,7 @@ static const struct snd_sof_debugfs_map cht_debugfs[] = {
         SOF_DEBUGFS_ACCESS_D0_ONLY},
        {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
         SOF_DEBUGFS_ACCESS_D0_ONLY},
-       {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
+       {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT,
         SOF_DEBUGFS_ACCESS_ALWAYS},
 };
 
@@ -145,33 +146,33 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
        struct sof_ipc_dsp_oops_xtensa xoops;
        struct sof_ipc_panic_info panic_info;
        u32 stack[BYT_STACK_DUMP_SIZE];
-       u32 status, panic, imrd, imrx;
+       u64 status, panic, imrd, imrx;
 
        /* now try generic SOF status messages */
-       status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
-       panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX);
+       status = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
+       panic = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
        byt_get_registers(sdev, &xoops, &panic_info, stack,
                          BYT_STACK_DUMP_SIZE);
        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
                           BYT_STACK_DUMP_SIZE);
 
        /* provide some context for firmware debug */
-       imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX);
-       imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD);
+       imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
+       imrd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRD);
        dev_err(sdev->dev,
-               "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
+               "error: ipc host -> DSP: pending %s complete %s raw 0x%llx\n",
                (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
                (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
        dev_err(sdev->dev,
-               "error: mask host: pending %s complete %s raw 0x%8.8x\n",
+               "error: mask host: pending %s complete %s raw 0x%llx\n",
                (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
                (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
        dev_err(sdev->dev,
-               "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
+               "error: ipc DSP -> host: pending %s complete %s raw 0x%llx\n",
                (status & SHIM_IPCD_BUSY) ? "yes" : "no",
                (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
        dev_err(sdev->dev,
-               "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
+               "error: mask DSP: pending %s complete %s raw 0x%llx\n",
                (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
                (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
 
index 9a9a381..432d12b 100644 (file)
@@ -50,8 +50,7 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
 
        while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) {
                /* read in ext structure */
-               offset += sizeof(*ext_hdr);
-               snd_sof_dsp_block_read(sdev, bar, offset,
+               snd_sof_dsp_block_read(sdev, bar, offset + sizeof(*ext_hdr),
                                   (void *)((u8 *)ext_data + sizeof(*ext_hdr)),
                                   ext_hdr->hdr.size - sizeof(*ext_hdr));
 
@@ -61,11 +60,15 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
                /* process structure data */
                switch (ext_hdr->type) {
                case SOF_IPC_EXT_DMA_BUFFER:
+                       ret = 0;
                        break;
                case SOF_IPC_EXT_WINDOW:
                        ret = get_ext_windows(sdev, ext_hdr);
                        break;
                default:
+                       dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n",
+                                ext_hdr->type, ext_hdr->hdr.size);
+                       ret = 0;
                        break;
                }
 
index d82ab98..e20b806 100644 (file)
@@ -3132,7 +3132,9 @@ found:
        case SOF_DAI_INTEL_SSP:
        case SOF_DAI_INTEL_DMIC:
        case SOF_DAI_INTEL_ALH:
-               /* no resource needs to be released for SSP, DMIC and ALH */
+       case SOF_DAI_IMX_SAI:
+       case SOF_DAI_IMX_ESAI:
+               /* no resource needs to be released for all cases above */
                break;
        case SOF_DAI_INTEL_HDA:
                ret = sof_link_hda_unload(sdev, link);
index 2769360..03cd7c1 100644 (file)
@@ -131,8 +131,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
index 67c21f9..820e575 100644 (file)
@@ -164,8 +164,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
@@ -323,6 +324,8 @@ struct kvm_vcpu_events {
 #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_ARM_VCPU_PVTIME_CTRL       2
+#define   KVM_ARM_VCPU_PVTIME_IPA      0
 
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_VCPU2_SHIFT                28
index b0f72de..264e266 100644 (file)
@@ -667,6 +667,8 @@ struct kvm_ppc_cpu_char {
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES       1       /* 64-bit source attributes */
+#define KVM_DEV_XICS_GRP_CTRL          2
+#define   KVM_DEV_XICS_NR_SERVERS      1
 
 /* Layout of 64-bit source attribute values */
 #define  KVM_XICS_DESTINATION_SHIFT    0
@@ -683,6 +685,7 @@ struct kvm_ppc_cpu_char {
 #define KVM_DEV_XIVE_GRP_CTRL          1
 #define   KVM_DEV_XIVE_RESET           1
 #define   KVM_DEV_XIVE_EQ_SYNC         2
+#define   KVM_DEV_XIVE_NR_SERVERS      3
 #define KVM_DEV_XIVE_GRP_SOURCE                2       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_EQ_CONFIG     4       /* 64-bit EQ identifier */
index 0652d3e..e9b6249 100644 (file)
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #define X86_FEATURE_IRPERF             (13*32+ 1) /* Instructions Retired Count */
 #define X86_FEATURE_XSAVEERPTR         (13*32+ 2) /* Always save/restore FP error pointers */
+#define X86_FEATURE_RDPRU              (13*32+ 4) /* Read processor register at user level */
 #define X86_FEATURE_WBNOINVD           (13*32+ 9) /* WBNOINVD instruction */
 #define X86_FEATURE_AMD_IBPB           (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_BUG_MDS                    X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
 #define X86_BUG_MSBDS_ONLY             X86_BUG(20) /* CPU is only affected by the  MSDBS variant of BUG_MDS */
 #define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
+#define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
+#define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 20ce682..084e98d 100644 (file)
                                                  * Microarchitectural Data
                                                  * Sampling (MDS) vulnerabilities.
                                                  */
+#define ARCH_CAP_PSCHANGE_MC_NO                BIT(6)   /*
+                                                 * The processor is not susceptible to a
+                                                 * machine check error due to modifying the
+                                                 * code page size along with either the
+                                                 * physical address or cache type
+                                                 * without TLB invalidation.
+                                                 */
+#define ARCH_CAP_TSX_CTRL_MSR          BIT(7)  /* MSR for TSX control is available. */
+#define ARCH_CAP_TAA_NO                        BIT(8)  /*
+                                                * Not susceptible to
+                                                * TSX Async Abort (TAA) vulnerabilities.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
 
+#define MSR_IA32_TSX_CTRL              0x00000122
+#define TSX_CTRL_RTM_DISABLE           BIT(0)  /* Disable RTM feature */
+#define TSX_CTRL_CPUID_CLEAR           BIT(1)  /* Disable TSX enumeration */
+
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
 #define MSR_IA32_SYSENTER_EIP          0x00000176
 #define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD_PPIN_CTL               0xc00102f0
+#define MSR_AMD_PPIN                   0xc00102f1
 #define MSR_AMD64_LS_CFG               0xc0011020
 #define MSR_AMD64_DC_CFG               0xc0011022
 #define MSR_AMD64_BU_CFG2              0xc001102a
index 9274866..df767af 100644 (file)
@@ -28,8 +28,8 @@
  * Output:
  * rax original destination
  */
-ENTRY(__memcpy)
-ENTRY(memcpy)
+SYM_FUNC_START_ALIAS(__memcpy)
+SYM_FUNC_START_LOCAL(memcpy)
        ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
                      "jmp memcpy_erms", X86_FEATURE_ERMS
 
@@ -41,8 +41,8 @@ ENTRY(memcpy)
        movl %edx, %ecx
        rep movsb
        ret
-ENDPROC(memcpy)
-ENDPROC(__memcpy)
+SYM_FUNC_END(memcpy)
+SYM_FUNC_END_ALIAS(__memcpy)
 EXPORT_SYMBOL(memcpy)
 EXPORT_SYMBOL(__memcpy)
 
@@ -50,14 +50,14 @@ EXPORT_SYMBOL(__memcpy)
  * memcpy_erms() - enhanced fast string memcpy. This is faster and
  * simpler than memcpy. Use memcpy_erms when possible.
  */
-ENTRY(memcpy_erms)
+SYM_FUNC_START(memcpy_erms)
        movq %rdi, %rax
        movq %rdx, %rcx
        rep movsb
        ret
-ENDPROC(memcpy_erms)
+SYM_FUNC_END(memcpy_erms)
 
-ENTRY(memcpy_orig)
+SYM_FUNC_START(memcpy_orig)
        movq %rdi, %rax
 
        cmpq $0x20, %rdx
@@ -182,7 +182,7 @@ ENTRY(memcpy_orig)
 
 .Lend:
        retq
-ENDPROC(memcpy_orig)
+SYM_FUNC_END(memcpy_orig)
 
 #ifndef CONFIG_UML
 
@@ -193,7 +193,7 @@ MCSAFE_TEST_CTL
  * Note that we only catch machine checks when reading the source addresses.
  * Writes to target are posted and don't generate machine checks.
  */
-ENTRY(__memcpy_mcsafe)
+SYM_FUNC_START(__memcpy_mcsafe)
        cmpl $8, %edx
        /* Less than 8 bytes? Go to byte copy loop */
        jb .L_no_whole_words
@@ -260,7 +260,7 @@ ENTRY(__memcpy_mcsafe)
        xorl %eax, %eax
 .L_done:
        ret
-ENDPROC(__memcpy_mcsafe)
+SYM_FUNC_END(__memcpy_mcsafe)
 EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
 
        .section .fixup, "ax"
index f8f3dc0..fd5d25a 100644 (file)
@@ -18,8 +18,8 @@
  *
  * rax   original destination
  */
-ENTRY(memset)
-ENTRY(__memset)
+SYM_FUNC_START_ALIAS(memset)
+SYM_FUNC_START(__memset)
        /*
         * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
         * to use it when possible. If not available, use fast string instructions.
@@ -42,8 +42,8 @@ ENTRY(__memset)
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset)
-ENDPROC(__memset)
+SYM_FUNC_END(__memset)
+SYM_FUNC_END_ALIAS(memset)
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses
@@ -56,16 +56,16 @@ ENDPROC(__memset)
  *
  * rax   original destination
  */
-ENTRY(memset_erms)
+SYM_FUNC_START(memset_erms)
        movq %rdi,%r9
        movb %sil,%al
        movq %rdx,%rcx
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset_erms)
+SYM_FUNC_END(memset_erms)
 
-ENTRY(memset_orig)
+SYM_FUNC_START(memset_orig)
        movq %rdi,%r10
 
        /* expand byte value  */
@@ -136,4 +136,4 @@ ENTRY(memset_orig)
        subq %r8,%rdx
        jmp .Lafter_bad_alignment
 .Lfinal:
-ENDPROC(memset_orig)
+SYM_FUNC_END(memset_orig)
index 8a5b2f8..868bf79 100644 (file)
@@ -778,11 +778,12 @@ struct drm_syncobj_array {
        __u32 pad;
 };
 
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */
 struct drm_syncobj_timeline_array {
        __u64 handles;
        __u64 points;
        __u32 count_handles;
-       __u32 pad;
+       __u32 flags;
 };
 
 
index 469dc51..5400d7e 100644 (file)
@@ -611,6 +611,13 @@ typedef struct drm_i915_irq_wait {
  * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
  */
 #define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
+
+/*
+ * Revision of the i915-perf uAPI. The value returned helps determine what
+ * i915-perf features are available. See drm_i915_perf_property_id.
+ */
+#define I915_PARAM_PERF_REVISION       54
+
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1565,6 +1572,21 @@ struct drm_i915_gem_context_param {
  *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
  */
 #define I915_CONTEXT_PARAM_ENGINES     0xa
+
+/*
+ * I915_CONTEXT_PARAM_PERSISTENCE:
+ *
+ * Allow the context and active rendering to survive the process until
+ * completion. Persistence allows fire-and-forget clients to queue up a
+ * bunch of work, hand the output over to a display server and then quit.
+ * If the context is marked as not persistent, upon closing (either via
+ * an explicit DRM_I915_GEM_CONTEXT_DESTROY or implicitly from file closure
+ * or process termination), the context and any outstanding requests will be
+ * cancelled (and exported fences for cancelled requests marked as -EIO).
+ *
+ * By default, new contexts allow persistence.
+ */
+#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
 /* Must be kept compact -- no holes and well documented */
 
        __u64 value;
@@ -1844,23 +1866,31 @@ enum drm_i915_perf_property_id {
         * Open the stream for a specific context handle (as used with
         * execbuffer2). A stream opened for a specific context this way
         * won't typically require root privileges.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_CTX_HANDLE = 1,
 
        /**
         * A value of 1 requests the inclusion of raw OA unit reports as
         * part of stream samples.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_SAMPLE_OA,
 
        /**
         * The value specifies which set of OA unit metrics should be
         * be configured, defining the contents of any OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_METRICS_SET,
 
        /**
         * The value specifies the size and layout of OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_FORMAT,
 
@@ -1870,9 +1900,22 @@ enum drm_i915_perf_property_id {
         * from this exponent as follows:
         *
         *   80ns * 2^(period_exponent + 1)
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_EXPONENT,
 
+       /**
+        * Specifying this property is only valid when specify a context to
+        * filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
+        * will hold preemption of the particular context we want to gather
+        * performance data about. The execbuf2 submissions must include a
+        * drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
+        *
+        * This property is available in perf revision 3.
+        */
+       DRM_I915_PERF_PROP_HOLD_PREEMPTION,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
@@ -1901,6 +1944,8 @@ struct drm_i915_perf_open_param {
  * to close and re-open a stream with the same configuration.
  *
  * It's undefined whether any pending data for the stream will be lost.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
 
@@ -1908,10 +1953,25 @@ struct drm_i915_perf_open_param {
  * Disable data capture for a stream.
  *
  * It is an error to try and read a stream that is disabled.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_DISABLE        _IO('i', 0x1)
 
 /**
+ * Change metrics_set captured by a stream.
+ *
+ * If the stream is bound to a specific context, the configuration change
+ * will performed inline with that context such that it takes effect before
+ * the next execbuf submission.
+ *
+ * Returns the previously bound metrics set id, or a negative error code.
+ *
+ * This ioctl is available in perf revision 2.
+ */
+#define I915_PERF_IOCTL_CONFIG _IO('i', 0x2)
+
+/**
  * Common to all i915 perf records
  */
 struct drm_i915_perf_record_header {
@@ -1984,6 +2044,7 @@ struct drm_i915_query_item {
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO    1
 #define DRM_I915_QUERY_ENGINE_INFO     2
+#define DRM_I915_QUERY_PERF_CONFIG      3
 /* Must be kept compact -- no holes and well documented */
 
        /*
@@ -1995,9 +2056,18 @@ struct drm_i915_query_item {
        __s32 length;
 
        /*
-        * Unused for now. Must be cleared to zero.
+        * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
+        *
+        * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the
+        * following :
+        *         - DRM_I915_QUERY_PERF_CONFIG_LIST
+        *         - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
+        *         - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
         */
        __u32 flags;
+#define DRM_I915_QUERY_PERF_CONFIG_LIST          1
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID   3
 
        /*
         * Data will be written at the location pointed by data_ptr when the
@@ -2033,8 +2103,10 @@ struct drm_i915_query {
  *           (data[X / 8] >> (X % 8)) & 1
  *
  * - the subslice mask for each slice with one bit per subslice telling
- *   whether a subslice is available. The availability of subslice Y in slice
- *   X can be queried with the following formula :
+ *   whether a subslice is available. Gen12 has dual-subslices, which are
+ *   similar to two gen11 subslices. For gen12, this array represents dual-
+ *   subslices. The availability of subslice Y in slice X can be queried
+ *   with the following formula :
  *
  *           (data[subslice_offset +
  *                 X * subslice_stride +
@@ -2123,6 +2195,56 @@ struct drm_i915_query_engine_info {
        struct drm_i915_engine_info engines[];
 };
 
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_PERF_CONFIG.
+ */
+struct drm_i915_query_perf_config {
+       union {
+               /*
+                * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets
+                * this fields to the number of configurations available.
+                */
+               __u64 n_configs;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                */
+               __u64 config;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                *
+                * String formatted like "%08x-%04x-%04x-%04x-%012x"
+                */
+               char uuid[36];
+       };
+
+       /*
+        * Unused for now. Must be cleared to zero.
+        */
+       __u32 flags;
+
+       /*
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 will
+        * write an array of __u64 of configuration identifiers.
+        *
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA, i915 will
+        * write a struct drm_i915_perf_oa_config. If the following fields of
+        * drm_i915_perf_oa_config are set not set to 0, i915 will write into
+        * the associated pointers the values of submitted when the
+        * configuration was created :
+        *
+        *         - n_mux_regs
+        *         - n_boolean_regs
+        *         - n_flex_regs
+        */
+       __u8 data[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 39ccfe9..1beb174 100644 (file)
@@ -17,7 +17,8 @@
 #define FSCRYPT_POLICY_FLAGS_PAD_32            0x03
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
-#define FSCRYPT_POLICY_FLAGS_VALID             0x07
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
+#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1
index 52641d8..f0a16b4 100644 (file)
@@ -235,6 +235,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_NISV         28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -394,6 +395,11 @@ struct kvm_run {
                } eoi;
                /* KVM_EXIT_HYPERV */
                struct kvm_hyperv_exit hyperv;
+               /* KVM_EXIT_ARM_NISV */
+               struct {
+                       __u64 esr_iss;
+                       __u64 fault_ipa;
+               } arm_nisv;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -1000,6 +1006,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PMU_EVENT_FILTER 173
 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
 #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
+#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176
+#define KVM_CAP_ARM_NISV_TO_USER 177
+#define KVM_CAP_ARM_INJECT_EXT_DABT 178
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1227,6 +1236,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_ARM_VGIC_ITS      KVM_DEV_TYPE_ARM_VGIC_ITS
        KVM_DEV_TYPE_XIVE,
 #define KVM_DEV_TYPE_XIVE              KVM_DEV_TYPE_XIVE
+       KVM_DEV_TYPE_ARM_PV_TIME,
+#define KVM_DEV_TYPE_ARM_PV_TIME       KVM_DEV_TYPE_ARM_PV_TIME
        KVM_DEV_TYPE_MAX,
 };
 
@@ -1337,6 +1348,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_CPU_CHAR     _IOR(KVMIO,  0xb1, struct kvm_ppc_cpu_char)
 /* Available with KVM_CAP_PMU_EVENT_FILTER */
 #define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
+#define KVM_PPC_SVM_OFF                  _IO(KVMIO,  0xb3)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index 99335e1..4a02178 100644 (file)
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #define CLONE_IO               0x80000000      /* Clone io context */
 
+/* Flags for the clone3() syscall. */
+#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
+
 #ifndef __ASSEMBLY__
 /**
  * struct clone_args - arguments for the clone3 syscall
- * @flags:       Flags for the new process as listed above.
- *               All flags are valid except for CSIGNAL and
- *               CLONE_DETACHED.
- * @pidfd:       If CLONE_PIDFD is set, a pidfd will be
- *               returned in this argument.
- * @child_tid:   If CLONE_CHILD_SETTID is set, the TID of the
- *               child process will be returned in the child's
- *               memory.
- * @parent_tid:  If CLONE_PARENT_SETTID is set, the TID of
- *               the child process will be returned in the
- *               parent's memory.
- * @exit_signal: The exit_signal the parent process will be
- *               sent when the child exits.
- * @stack:       Specify the location of the stack for the
- *               child process.
- * @stack_size:  The size of the stack for the child process.
- * @tls:         If CLONE_SETTLS is set, the tls descriptor
- *               is set to tls.
+ * @flags:        Flags for the new process as listed above.
+ *                All flags are valid except for CSIGNAL and
+ *                CLONE_DETACHED.
+ * @pidfd:        If CLONE_PIDFD is set, a pidfd will be
+ *                returned in this argument.
+ * @child_tid:    If CLONE_CHILD_SETTID is set, the TID of the
+ *                child process will be returned in the child's
+ *                memory.
+ * @parent_tid:   If CLONE_PARENT_SETTID is set, the TID of
+ *                the child process will be returned in the
+ *                parent's memory.
+ * @exit_signal:  The exit_signal the parent process will be
+ *                sent when the child exits.
+ * @stack:        Specify the location of the stack for the
+ *                child process.
+ *                Note, @stack is expected to point to the
+ *                lowest address. The stack direction will be
+ *                determined by the kernel and set up
+ *                appropriately based on @stack_size.
+ * @stack_size:   The size of the stack for the child process.
+ * @tls:          If CLONE_SETTLS is set, the tls descriptor
+ *                is set to tls.
+ * @set_tid:      Pointer to an array of type *pid_t. The size
+ *                of the array is defined using @set_tid_size.
+ *                This array is used to select PIDs/TIDs for
+ *                newly created processes. The first element in
+ *                this defines the PID in the most nested PID
+ *                namespace. Each additional element in the array
+ *                defines the PID in the parent PID namespace of
+ *                the original PID namespace. If the array has
+ *                less entries than the number of currently
+ *                nested PID namespaces only the PIDs in the
+ *                corresponding namespaces are set.
+ * @set_tid_size: This defines the size of the array referenced
+ *                in @set_tid. This cannot be larger than the
+ *                kernel's limit of nested PID namespaces.
  *
  * The structure is versioned by size and thus extensible.
  * New struct members must go at the end of the struct and
@@ -68,10 +89,13 @@ struct clone_args {
        __aligned_u64 stack;
        __aligned_u64 stack_size;
        __aligned_u64 tls;
+       __aligned_u64 set_tid;
+       __aligned_u64 set_tid_size;
 };
 #endif
 
 #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
+#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
 
 /*
  * Scheduling policies
index 7b35e98..ad80a5c 100644 (file)
@@ -167,8 +167,8 @@ struct statx {
 #define STATX_ATTR_APPEND              0x00000020 /* [I] File is append-only */
 #define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
 #define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
-
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index cbb429f..c874c01 100644 (file)
@@ -39,11 +39,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_temp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_temp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_temp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 man_dir = $(prefix)/share/man
@@ -97,6 +98,7 @@ EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
 LIB_TARGET  = libtraceevent.a libtraceevent.so.$(EVENT_PARSE_VERSION)
 LIB_INSTALL = libtraceevent.a libtraceevent.so*
+LIB_INSTALL := $(addprefix $(OUTPUT),$(LIB_INSTALL))
 
 INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
 
@@ -207,10 +209,11 @@ define do_install
        $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2'
 endef
 
-PKG_CONFIG_FILE = libtraceevent.pc
+PKG_CONFIG_SOURCE_FILE = libtraceevent.pc
+PKG_CONFIG_FILE := $(addprefix $(OUTPUT),$(PKG_CONFIG_SOURCE_FILE))
 define do_install_pkgconfig_file
        if [ -n "${pkgconfig_dir}" ]; then                                      \
-               cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE};           \
+               cp -f ${PKG_CONFIG_SOURCE_FILE}.template ${PKG_CONFIG_FILE};    \
                sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE};            \
                sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \
                sed -i "s|LIB_DIR|${libdir}|g" ${PKG_CONFIG_FILE}; \
index f440989..349bb81 100644 (file)
@@ -32,11 +32,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_tmp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_tmp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_tmp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 
index 6a5bb2b..cf95bae 100644 (file)
@@ -68,10 +68,11 @@ OPTIONS
 -------
 -i::
 --input=<path>::
-        Input file name.
+        Input file name, for the 'report', 'diff' and 'buildid-list' subcommands.
 -o::
 --output=<path>::
-        Output file name.
+        Output file name, for the 'record' subcommand. Doesn't work with 'report',
+        just redirect the output to a file when using 'report'.
 --host::
         Collect host side performance profile.
 --guest::
index 6e2495c..4284307 100644 (file)
@@ -37,7 +37,7 @@
 
 .text
 .type perf_regs_load,%function
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        str r0, [r0, #R0]
        str r1, [r0, #R1]
        str r2, [r0, #R2]
@@ -56,4 +56,4 @@ ENTRY(perf_regs_load)
        str lr, [r0, #PC]       // store pc as lr in order to skip the call
                                //  to this function
        mov pc, lr
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index 0704251..d49de40 100644 (file)
@@ -7,7 +7,7 @@
 #define LDR_REG(r)     ldr x##r, [x0, 8 * r]
 #define SP     (8 * 31)
 #define PC     (8 * 32)
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        STR_REG(0)
        STR_REG(1)
        STR_REG(2)
@@ -44,4 +44,4 @@ ENTRY(perf_regs_load)
        str x30, [x0, #PC]
        LDR_REG(1)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index bbe5a0d..80f14f5 100644 (file)
@@ -28,7 +28,7 @@
 
 .text
 #ifdef HAVE_ARCH_X86_64_SUPPORT
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        movq %rax, AX(%rdi)
        movq %rbx, BX(%rdi)
        movq %rcx, CX(%rdi)
@@ -60,9 +60,9 @@ ENTRY(perf_regs_load)
        movq %r14, R14(%rdi)
        movq %r15, R15(%rdi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #else
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        push %edi
        movl 8(%esp), %edi
        movl %eax, AX(%edi)
@@ -88,7 +88,7 @@ ENTRY(perf_regs_load)
        movl $0, FS(%edi)
        movl $0, GS(%edi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #endif
 
 /*
index 9664a72..7e124a7 100644 (file)
@@ -403,17 +403,6 @@ static int perf_event__repipe_tracing_data(struct perf_session *session,
        return err;
 }
 
-static int perf_event__repipe_id_index(struct perf_session *session,
-                                      union perf_event *event)
-{
-       int err;
-
-       perf_event__repipe_synth(session->tool, event);
-       err = perf_event__process_id_index(session, event);
-
-       return err;
-}
-
 static int dso__read_build_id(struct dso *dso)
 {
        if (dso->has_build_id)
@@ -651,7 +640,7 @@ static int __cmd_inject(struct perf_inject *inject)
                inject->tool.comm           = perf_event__repipe_comm;
                inject->tool.namespaces     = perf_event__repipe_namespaces;
                inject->tool.exit           = perf_event__repipe_exit;
-               inject->tool.id_index       = perf_event__repipe_id_index;
+               inject->tool.id_index       = perf_event__process_id_index;
                inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
                inject->tool.auxtrace       = perf_event__process_auxtrace;
                inject->tool.aux            = perf_event__drop_aux;
index b5063d3..fb19ef6 100644 (file)
@@ -832,7 +832,7 @@ try_again:
                        if ((errno == EINVAL || errno == EBADF) &&
                            pos->leader != pos &&
                            pos->weak_group) {
-                               pos = perf_evlist__reset_weak_group(evlist, pos);
+                               pos = perf_evlist__reset_weak_group(evlist, pos, true);
                                goto try_again;
                        }
                        rc = -errno;
index 830d563..387311c 100644 (file)
@@ -388,6 +388,14 @@ static int report__setup_sample_type(struct report *rep)
                }
        }
 
+       if (sort__mode == SORT_MODE__MEMORY) {
+               if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
+                       ui__error("Selected --mem-mode but no mem data. "
+                                 "Did you call perf record without -d?\n");
+                       return -1;
+               }
+       }
+
        if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
                if ((sample_type & PERF_SAMPLE_REGS_USER) &&
                    (sample_type & PERF_SAMPLE_STACK_USER)) {
index 0a15253..a098c2e 100644 (file)
@@ -65,6 +65,7 @@
 #include "util/target.h"
 #include "util/time-utils.h"
 #include "util/top.h"
+#include "util/affinity.h"
 #include "asm/bug.h"
 
 #include <linux/time64.h>
@@ -265,15 +266,10 @@ static int read_single_counter(struct evsel *counter, int cpu,
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
  */
-static int read_counter(struct evsel *counter, struct timespec *rs)
+static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu)
 {
        int nthreads = perf_thread_map__nr(evsel_list->core.threads);
-       int ncpus, cpu, thread;
-
-       if (target__has_cpu(&target) && !target__has_per_thread(&target))
-               ncpus = perf_evsel__nr_cpus(counter);
-       else
-               ncpus = 1;
+       int thread;
 
        if (!counter->supported)
                return -ENOENT;
@@ -282,40 +278,38 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
                nthreads = 1;
 
        for (thread = 0; thread < nthreads; thread++) {
-               for (cpu = 0; cpu < ncpus; cpu++) {
-                       struct perf_counts_values *count;
-
-                       count = perf_counts(counter->counts, cpu, thread);
-
-                       /*
-                        * The leader's group read loads data into its group members
-                        * (via perf_evsel__read_counter) and sets threir count->loaded.
-                        */
-                       if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
-                           read_single_counter(counter, cpu, thread, rs)) {
-                               counter->counts->scaled = -1;
-                               perf_counts(counter->counts, cpu, thread)->ena = 0;
-                               perf_counts(counter->counts, cpu, thread)->run = 0;
-                               return -1;
-                       }
+               struct perf_counts_values *count;
 
-                       perf_counts__set_loaded(counter->counts, cpu, thread, false);
+               count = perf_counts(counter->counts, cpu, thread);
 
-                       if (STAT_RECORD) {
-                               if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
-                                       pr_err("failed to write stat event\n");
-                                       return -1;
-                               }
-                       }
+               /*
+                * The leader's group read loads data into its group members
+                * (via perf_evsel__read_counter()) and sets their count->loaded.
+                */
+               if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
+                   read_single_counter(counter, cpu, thread, rs)) {
+                       counter->counts->scaled = -1;
+                       perf_counts(counter->counts, cpu, thread)->ena = 0;
+                       perf_counts(counter->counts, cpu, thread)->run = 0;
+                       return -1;
+               }
+
+               perf_counts__set_loaded(counter->counts, cpu, thread, false);
 
-                       if (verbose > 1) {
-                               fprintf(stat_config.output,
-                                       "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-                                               perf_evsel__name(counter),
-                                               cpu,
-                                               count->val, count->ena, count->run);
+               if (STAT_RECORD) {
+                       if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
+                               pr_err("failed to write stat event\n");
+                               return -1;
                        }
                }
+
+               if (verbose > 1) {
+                       fprintf(stat_config.output,
+                               "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+                                       perf_evsel__name(counter),
+                                       cpu,
+                                       count->val, count->ena, count->run);
+               }
        }
 
        return 0;
@@ -324,15 +318,37 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
 static void read_counters(struct timespec *rs)
 {
        struct evsel *counter;
-       int ret;
+       struct affinity affinity;
+       int i, ncpus, cpu;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+
+       ncpus = perf_cpu_map__nr(evsel_list->core.all_cpus);
+       if (!target__has_cpu(&target) || target__has_per_thread(&target))
+               ncpus = 1;
+       evlist__for_each_cpu(evsel_list, i, cpu) {
+               if (i >= ncpus)
+                       break;
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (!counter->err) {
+                               counter->err = read_counter_cpu(counter, rs,
+                                                               counter->cpu_iter - 1);
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
        evlist__for_each_entry(evsel_list, counter) {
-               ret = read_counter(counter, rs);
-               if (ret)
+               if (counter->err)
                        pr_debug("failed to read counter %s\n", counter->name);
-
-               if (ret == 0 && perf_stat_process_counter(&stat_config, counter))
+               if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))
                        pr_warning("failed to process counter %s\n", counter->name);
+               counter->err = 0;
        }
 }
 
@@ -420,6 +436,62 @@ static bool is_target_alive(struct target *_target,
        return false;
 }
 
+enum counter_recovery {
+       COUNTER_SKIP,
+       COUNTER_RETRY,
+       COUNTER_FATAL,
+};
+
+static enum counter_recovery stat_handle_error(struct evsel *counter)
+{
+       char msg[BUFSIZ];
+       /*
+        * PPC returns ENXIO for HW counters until 2.6.37
+        * (behavior changed with commit b0a873e).
+        */
+       if (errno == EINVAL || errno == ENOSYS ||
+           errno == ENOENT || errno == EOPNOTSUPP ||
+           errno == ENXIO) {
+               if (verbose > 0)
+                       ui__warning("%s event is not supported by the kernel.\n",
+                                   perf_evsel__name(counter));
+               counter->supported = false;
+               /*
+                * errored is a sticky flag that means one of the counter's
+                * cpu event had a problem and needs to be reexamined.
+                */
+               counter->errored = true;
+
+               if ((counter->leader != counter) ||
+                   !(counter->leader->core.nr_members > 1))
+                       return COUNTER_SKIP;
+       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
+               if (verbose > 0)
+                       ui__warning("%s\n", msg);
+               return COUNTER_RETRY;
+       } else if (target__has_per_thread(&target) &&
+                  evsel_list->core.threads &&
+                  evsel_list->core.threads->err_thread != -1) {
+               /*
+                * For global --per-thread case, skip current
+                * error thread.
+                */
+               if (!thread_map__remove(evsel_list->core.threads,
+                                       evsel_list->core.threads->err_thread)) {
+                       evsel_list->core.threads->err_thread = -1;
+                       return COUNTER_RETRY;
+               }
+       }
+
+       perf_evsel__open_strerror(counter, &target,
+                                 errno, msg, sizeof(msg));
+       ui__error("%s\n", msg);
+
+       if (child_pid != -1)
+               kill(child_pid, SIGTERM);
+       return COUNTER_FATAL;
+}
+
 static int __run_perf_stat(int argc, const char **argv, int run_idx)
 {
        int interval = stat_config.interval;
@@ -433,6 +505,9 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        int status = 0;
        const bool forks = (argc > 0);
        bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
+       struct affinity affinity;
+       int i, cpu;
+       bool second_pass = false;
 
        if (interval) {
                ts.tv_sec  = interval / USEC_PER_MSEC;
@@ -457,61 +532,104 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        if (group)
                perf_evlist__set_leader(evsel_list);
 
-       evlist__for_each_entry(evsel_list, counter) {
+       if (affinity__setup(&affinity) < 0)
+               return -1;
+
+       evlist__for_each_cpu (evsel_list, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (counter->reset_group || counter->errored)
+                               continue;
 try_again:
-               if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
-
-                       /* Weak group failed. Reset the group. */
-                       if ((errno == EINVAL || errno == EBADF) &&
-                           counter->leader != counter &&
-                           counter->weak_group) {
-                               counter = perf_evlist__reset_weak_group(evsel_list, counter);
-                               goto try_again;
-                       }
+                       if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                    counter->cpu_iter - 1) < 0) {
 
-                       /*
-                        * PPC returns ENXIO for HW counters until 2.6.37
-                        * (behavior changed with commit b0a873e).
-                        */
-                       if (errno == EINVAL || errno == ENOSYS ||
-                           errno == ENOENT || errno == EOPNOTSUPP ||
-                           errno == ENXIO) {
-                               if (verbose > 0)
-                                       ui__warning("%s event is not supported by the kernel.\n",
-                                                   perf_evsel__name(counter));
-                               counter->supported = false;
-
-                               if ((counter->leader != counter) ||
-                                   !(counter->leader->core.nr_members > 1))
-                                       continue;
-                       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
-                                if (verbose > 0)
-                                        ui__warning("%s\n", msg);
-                                goto try_again;
-                       } else if (target__has_per_thread(&target) &&
-                                  evsel_list->core.threads &&
-                                  evsel_list->core.threads->err_thread != -1) {
                                /*
-                                * For global --per-thread case, skip current
-                                * error thread.
+                                * Weak group failed. We cannot just undo this here
+                                * because earlier CPUs might be in group mode, and the kernel
+                                * doesn't support mixing group and non group reads. Defer
+                                * it to later.
+                                * Don't close here because we're in the wrong affinity.
                                 */
-                               if (!thread_map__remove(evsel_list->core.threads,
-                                                       evsel_list->core.threads->err_thread)) {
-                                       evsel_list->core.threads->err_thread = -1;
+                               if ((errno == EINVAL || errno == EBADF) &&
+                                   counter->leader != counter &&
+                                   counter->weak_group) {
+                                       perf_evlist__reset_weak_group(evsel_list, counter, false);
+                                       assert(counter->reset_group);
+                                       second_pass = true;
+                                       continue;
+                               }
+
+                               switch (stat_handle_error(counter)) {
+                               case COUNTER_FATAL:
+                                       return -1;
+                               case COUNTER_RETRY:
                                        goto try_again;
+                               case COUNTER_SKIP:
+                                       continue;
+                               default:
+                                       break;
                                }
+
                        }
+                       counter->supported = true;
+               }
+       }
 
-                       perf_evsel__open_strerror(counter, &target,
-                                                 errno, msg, sizeof(msg));
-                       ui__error("%s\n", msg);
+       if (second_pass) {
+               /*
+                * Now redo all the weak group after closing them,
+                * and also close errored counters.
+                */
 
-                       if (child_pid != -1)
-                               kill(child_pid, SIGTERM);
+               evlist__for_each_cpu(evsel_list, i, cpu) {
+                       affinity__set(&affinity, cpu);
+                       /* First close errored or weak retry */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip_no_inc(counter, cpu))
+                                       continue;
+                               perf_evsel__close_cpu(&counter->core, counter->cpu_iter);
+                       }
+                       /* Now reopen weak */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip(counter, cpu))
+                                       continue;
+                               if (!counter->reset_group)
+                                       continue;
+try_again_reset:
+                               pr_debug2("reopening weak %s\n", perf_evsel__name(counter));
+                               if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                            counter->cpu_iter - 1) < 0) {
+
+                                       switch (stat_handle_error(counter)) {
+                                       case COUNTER_FATAL:
+                                               return -1;
+                                       case COUNTER_RETRY:
+                                               goto try_again_reset;
+                                       case COUNTER_SKIP:
+                                               continue;
+                                       default:
+                                               break;
+                                       }
+                               }
+                               counter->supported = true;
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
-                       return -1;
+       evlist__for_each_entry(evsel_list, counter) {
+               if (!counter->supported) {
+                       perf_evsel__free_fd(&counter->core);
+                       continue;
                }
-               counter->supported = true;
 
                l = strlen(counter->unit);
                if (l > stat_config.unit_width)
index dc80044..795e353 100644 (file)
@@ -1568,9 +1568,13 @@ int cmd_top(int argc, const char **argv)
         */
        status = perf_env__read_cpuid(&perf_env);
        if (status) {
-               pr_err("Couldn't read the cpuid for this machine: %s\n",
-                      str_error_r(errno, errbuf, sizeof(errbuf)));
-               goto out_delete_evlist;
+               /*
+                * Some arches do not provide a get_cpuid(), so just use pr_debug, otherwise
+                * warn the user explicitely.
+                */
+               eprintf(status == ENOSYS ? 1 : 0, verbose,
+                       "Couldn't read the cpuid for this machine: %s\n",
+                       str_error_r(errno, errbuf, sizeof(errbuf)));
        }
        top.evlist->env = &perf_env;
 
index a1dc167..68039a9 100755 (executable)
@@ -110,8 +110,8 @@ for i in $FILES; do
 done
 
 # diff with extra ignore lines
-check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
-check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
+check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memcpy_\(erms\|orig\))"'
+check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"'
 check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"'
 check include/uapi/linux/mman.h       '-I "^#include <\(uapi/\)*asm/mman.h>"'
 check include/linux/ctype.h          '-I "isdigit("'
index 2ca1faf..f93f4e7 100644 (file)
@@ -68,14 +68,28 @@ static struct perf_cpu_map *cpu_map__default_new(void)
        return cpus;
 }
 
+static int cmp_int(const void *a, const void *b)
+{
+       return *(const int *)a - *(const int*)b;
+}
+
 static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 {
        size_t payload_size = nr_cpus * sizeof(int);
        struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+       int i, j;
 
        if (cpus != NULL) {
-               cpus->nr = nr_cpus;
                memcpy(cpus->map, tmp_cpus, payload_size);
+               qsort(cpus->map, nr_cpus, sizeof(int), cmp_int);
+               /* Remove dups */
+               j = 0;
+               for (i = 0; i < nr_cpus; i++) {
+                       if (i == 0 || cpus->map[i] != cpus->map[i - 1])
+                               cpus->map[j++] = cpus->map[i];
+               }
+               cpus->nr = j;
+               assert(j <= nr_cpus);
                refcount_set(&cpus->refcnt, 1);
        }
 
@@ -272,3 +286,60 @@ int perf_cpu_map__max(struct perf_cpu_map *map)
 
        return max;
 }
+
+/*
+ * Merge two cpumaps
+ *
+ * orig either gets freed and replaced with a new map, or reused
+ * with no reference count change (similar to "realloc")
+ * other has its reference count increased.
+ */
+
+struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                        struct perf_cpu_map *other)
+{
+       int *tmp_cpus;
+       int tmp_len;
+       int i, j, k;
+       struct perf_cpu_map *merged;
+
+       if (!orig && !other)
+               return NULL;
+       if (!orig) {
+               perf_cpu_map__get(other);
+               return other;
+       }
+       if (!other)
+               return orig;
+       if (orig->nr == other->nr &&
+           !memcmp(orig->map, other->map, orig->nr * sizeof(int)))
+               return orig;
+
+       tmp_len = orig->nr + other->nr;
+       tmp_cpus = malloc(tmp_len * sizeof(int));
+       if (!tmp_cpus)
+               return NULL;
+
+       /* Standard merge algorithm from wikipedia */
+       i = j = k = 0;
+       while (i < orig->nr && j < other->nr) {
+               if (orig->map[i] <= other->map[j]) {
+                       if (orig->map[i] == other->map[j])
+                               j++;
+                       tmp_cpus[k++] = orig->map[i++];
+               } else
+                       tmp_cpus[k++] = other->map[j++];
+       }
+
+       while (i < orig->nr)
+               tmp_cpus[k++] = orig->map[i++];
+
+       while (j < other->nr)
+               tmp_cpus[k++] = other->map[j++];
+       assert(k <= tmp_len);
+
+       merged = cpu_map__trim_new(k, tmp_cpus);
+       free(tmp_cpus);
+       perf_cpu_map__put(orig);
+       return merged;
+}
index 205ddbb..ae9e65a 100644 (file)
@@ -54,6 +54,7 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
 
        perf_thread_map__put(evsel->threads);
        evsel->threads = perf_thread_map__get(evlist->threads);
+       evlist->all_cpus = perf_cpu_map__merge(evlist->all_cpus, evsel->cpus);
 }
 
 static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
index 5a89857..4dc0628 100644 (file)
@@ -114,16 +114,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
        return err;
 }
 
+static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu)
+{
+       int thread;
+
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
+               if (FD(evsel, cpu, thread) >= 0)
+                       close(FD(evsel, cpu, thread));
+               FD(evsel, cpu, thread) = -1;
+       }
+}
+
 void perf_evsel__close_fd(struct perf_evsel *evsel)
 {
-       int cpu, thread;
+       int cpu;
 
        for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
-                       if (FD(evsel, cpu, thread) >= 0)
-                               close(FD(evsel, cpu, thread));
-                       FD(evsel, cpu, thread) = -1;
-               }
+               perf_evsel__close_fd_cpu(evsel, cpu);
 }
 
 void perf_evsel__free_fd(struct perf_evsel *evsel)
@@ -141,6 +148,14 @@ void perf_evsel__close(struct perf_evsel *evsel)
        perf_evsel__free_fd(evsel);
 }
 
+void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu)
+{
+       if (evsel->fd == NULL)
+               return;
+
+       perf_evsel__close_fd_cpu(evsel, cpu);
+}
+
 int perf_evsel__read_size(struct perf_evsel *evsel)
 {
        u64 read_format = evsel->attr.read_format;
@@ -183,38 +198,61 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 }
 
 static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
-                                int ioc,  void *arg)
+                                int ioc,  void *arg,
+                                int cpu)
 {
-       int cpu, thread;
+       int thread;
 
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
-                       int fd = FD(evsel, cpu, thread),
-                           err = ioctl(fd, ioc, arg);
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
+               int fd = FD(evsel, cpu, thread),
+                   err = ioctl(fd, ioc, arg);
 
-                       if (err)
-                               return err;
-               }
+               if (err)
+                       return err;
        }
 
        return 0;
 }
 
+int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu);
+}
+
 int perf_evsel__enable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i);
+       return err;
+}
+
+int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu);
 }
 
 int perf_evsel__disable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i);
+       return err;
 }
 
 int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
 {
-       return perf_evsel__run_ioctl(evsel,
+       int err = 0, i;
+
+       for (i = 0; i < evsel->cpus->nr && !err; i++)
+               err = perf_evsel__run_ioctl(evsel,
                                     PERF_EVENT_IOC_SET_FILTER,
-                                    (void *)filter);
+                                    (void *)filter, i);
+       return err;
 }
 
 struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
index a2fbccf..74dc8c3 100644 (file)
@@ -18,6 +18,7 @@ struct perf_evlist {
        int                      nr_entries;
        bool                     has_user_cpus;
        struct perf_cpu_map     *cpus;
+       struct perf_cpu_map     *all_cpus;
        struct perf_thread_map  *threads;
        int                      nr_mmaps;
        size_t                   mmap_len;
index ac9aa49..6a17ad7 100644 (file)
@@ -12,6 +12,8 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                                    struct perf_cpu_map *other);
 LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
 LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
 LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
index 557f581..c82ec39 100644 (file)
@@ -26,10 +26,13 @@ LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
 LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
                                 struct perf_thread_map *threads);
 LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel);
+LIBPERF_API void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
                                 struct perf_counts_values *count);
 LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
 LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
 LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
index 436ce33..5da8296 100644 (file)
@@ -32,7 +32,7 @@
                "EventCode": "132",
                "EventName": "DTLB1_GPAGE_WRITES",
                "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
-               "PublicDescription": "Counter:132       Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
+               "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
        },
        {
                "Unit": "CPU-M-CF",
index 6861815..89e0707 100644 (file)
@@ -4,7 +4,7 @@
                "EventCode": "128",
                "EventName": "L1D_RO_EXCL_WRITES",
                "BriefDescription": "L1D Read-only Exclusive Writes",
-               "PublicDescription": "L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
+               "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
        },
        {
                "Unit": "CPU-M-CF",
index bc7151d..45a34ce 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 49c5f12..961fe43 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 113d19e..746734c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 2ba32af..f946532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c80f16f..5402cd3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e501729..832f3cb 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e244696..d69b2a8 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 9294769..5f465fd 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 603ff9c..3e909b3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c6b485b..50c0532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 0ca539b..e7feb60 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 047d7e1..21d7a0c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index a3c595f..1692529 100644 (file)
@@ -54,6 +54,7 @@ perf-y += unit_number__scnprintf.o
 perf-y += mem2node.o
 perf-y += maps.o
 perf-y += time-utils-test.o
+perf-y += genelf.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
        $(call rule_mkdir)
index 7115aa3..5f05db7 100644 (file)
@@ -260,6 +260,11 @@ static struct test generic_tests[] = {
                .func = test__cpu_map_print,
        },
        {
+               .desc = "Merge cpu map",
+               .func = test__cpu_map_merge,
+       },
+
+       {
                .desc = "Probe SDT events",
                .func = test__sdt_event,
        },
@@ -297,6 +302,10 @@ static struct test generic_tests[] = {
                .func = test__time_utils,
        },
        {
+               .desc = "Test jit_write_elf",
+               .func = test__jit_write_elf,
+       },
+       {
                .desc = "maps__merge_in",
                .func = test__maps__merge_in,
        },
index 8a0d236..4ac5674 100644 (file)
@@ -120,3 +120,19 @@ int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_un
        TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1-10,12-20,22-30,32-40"));
        return 0;
 }
+
+int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+       struct perf_cpu_map *a = perf_cpu_map__new("4,2,1");
+       struct perf_cpu_map *b = perf_cpu_map__new("4,5,7");
+       struct perf_cpu_map *c = perf_cpu_map__merge(a, b);
+       char buf[100];
+
+       TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr == 5);
+       cpu_map__snprint(c, buf, sizeof(buf));
+       TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,7"));
+       perf_cpu_map__put(a);
+       perf_cpu_map__put(b);
+       perf_cpu_map__put(c);
+       return 0;
+}
index 1ee8704..1e8a9f5 100644 (file)
@@ -125,7 +125,7 @@ static int attach__cpu_disabled(struct evlist *evlist)
 
        evsel->core.attr.disabled = 1;
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err) {
                if (err == -EACCES)
                        return TEST_SKIP;
@@ -152,7 +152,7 @@ static int attach__cpu_enabled(struct evlist *evlist)
                return -1;
        }
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err == -EACCES)
                return TEST_SKIP;
 
diff --git a/tools/perf/tests/genelf.c b/tools/perf/tests/genelf.c
new file mode 100644 (file)
index 0000000..f797f98
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+
+#include "debug.h"
+#include "tests.h"
+
+#ifdef HAVE_JITDUMP
+#include <libelf.h>
+#include "../util/genelf.h"
+#endif
+
+#define TEMPL "/tmp/perf-test-XXXXXX"
+
+int test__jit_write_elf(struct test *test __maybe_unused,
+                       int subtest __maybe_unused)
+{
+#ifdef HAVE_JITDUMP
+       static unsigned char x86_code[] = {
+               0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
+               0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
+               0xCD, 0x80            /* int $0x80 */
+       };
+       char path[PATH_MAX];
+       int fd, ret;
+
+       strcpy(path, TEMPL);
+
+       fd = mkstemp(path);
+       if (fd < 0) {
+               perror("mkstemp failed");
+               return TEST_FAIL;
+       }
+
+       pr_info("Writing jit code to: %s\n", path);
+
+       ret = jit_write_elf(fd, 0, "main", x86_code, sizeof(x86_code),
+                       NULL, 0, NULL, 0, 0);
+       close(fd);
+
+       unlink(path);
+
+       return ret ? TEST_FAIL : 0;
+#else
+       return TEST_SKIP;
+#endif
+}
index 25aea38..9a160fe 100644 (file)
@@ -98,6 +98,7 @@ int test__event_update(struct test *test, int subtest);
 int test__event_times(struct test *test, int subtest);
 int test__backward_ring_buffer(struct test *test, int subtest);
 int test__cpu_map_print(struct test *test, int subtest);
+int test__cpu_map_merge(struct test *test, int subtest);
 int test__sdt_event(struct test *test, int subtest);
 int test__is_printable_array(struct test *test, int subtest);
 int test__bitmap_print(struct test *test, int subtest);
@@ -109,6 +110,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
 int test__mem2node(struct test *t, int subtest);
 int test__maps__merge_in(struct test *t, int subtest);
 int test__time_utils(struct test *t, int subtest);
+int test__jit_write_elf(struct test *test, int subtest);
 
 bool test__bp_signal_is_supported(void);
 bool test__bp_account_is_supported(void);
index 1a8d3be..062ca84 100644 (file)
@@ -45,6 +45,7 @@ static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size,
        P_FLAG(NEWPID);
        P_FLAG(NEWNET);
        P_FLAG(IO);
+       P_FLAG(CLEAR_SIGHAND);
 #undef P_FLAG
 
        if (flags)
index 57943f3..3a442f0 100644 (file)
@@ -63,4 +63,5 @@ int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res,
 
 int cpu_map__cpu(struct perf_cpu_map *cpus, int idx);
 bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);
+
 #endif /* __PERF_CPUMAP_H */
index fdce590..1548237 100644 (file)
@@ -18,6 +18,7 @@
 #include "debug.h"
 #include "units.h"
 #include <internal/lib.h> // page_size
+#include "affinity.h"
 #include "../perf.h"
 #include "asm/bug.h"
 #include "bpf-event.h"
@@ -342,14 +343,63 @@ static int perf_evlist__nr_threads(struct evlist *evlist,
                return perf_thread_map__nr(evlist->core.threads);
 }
 
+void evlist__cpu_iter_start(struct evlist *evlist)
+{
+       struct evsel *pos;
+
+       /*
+        * Reset the per evsel cpu_iter. This is needed because
+        * each evsel's cpumap may have a different index space,
+        * and some operations need the index to modify
+        * the FD xyarray (e.g. open, close)
+        */
+       evlist__for_each_entry(evlist, pos)
+               pos->cpu_iter = 0;
+}
+
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
+{
+       if (ev->cpu_iter >= ev->core.cpus->nr)
+               return true;
+       if (cpu >= 0 && ev->core.cpus->map[ev->cpu_iter] != cpu)
+               return true;
+       return false;
+}
+
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
+{
+       if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
+               ev->cpu_iter++;
+               return false;
+       }
+       return true;
+}
+
 void evlist__disable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__disable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
-               if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+               if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__disable(pos);
+               pos->disabled = true;
        }
 
        evlist->enabled = false;
@@ -358,11 +408,28 @@ void evlist__disable(struct evlist *evlist)
 void evlist__enable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__enable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
                if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__enable(pos);
+               pos->disabled = false;
        }
 
        evlist->enabled = true;
@@ -1137,9 +1204,35 @@ void perf_evlist__set_selected(struct evlist *evlist,
 void evlist__close(struct evlist *evlist)
 {
        struct evsel *evsel;
+       struct affinity affinity;
+       int cpu, i;
 
-       evlist__for_each_entry_reverse(evlist, evsel)
-               evsel__close(evsel);
+       /*
+        * With perf record core.cpus is usually NULL.
+        * Use the old method to handle this for now.
+        */
+       if (!evlist->core.cpus) {
+               evlist__for_each_entry_reverse(evlist, evsel)
+                       evsel__close(evsel);
+               return;
+       }
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry_reverse(evlist, evsel) {
+                       if (evsel__cpu_iter_skip(evsel, cpu))
+                           continue;
+                       perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
+       evlist__for_each_entry_reverse(evlist, evsel) {
+               perf_evsel__free_fd(&evsel->core);
+               perf_evsel__free_id(&evsel->core);
+       }
 }
 
 static int perf_evlist__create_syswide_maps(struct evlist *evlist)
@@ -1577,7 +1670,8 @@ void perf_evlist__force_leader(struct evlist *evlist)
 }
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
-                                                struct evsel *evsel)
+                                                struct evsel *evsel,
+                                               bool close)
 {
        struct evsel *c2, *leader;
        bool is_open = true;
@@ -1594,10 +1688,15 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
                if (c2 == evsel)
                        is_open = false;
                if (c2->leader == leader) {
-                       if (is_open)
+                       if (is_open && close)
                                perf_evsel__close(&c2->core);
                        c2->leader = c2;
                        c2->core.nr_members = 0;
+                       /*
+                        * Set this for all former members of the group
+                        * to indicate they get reopened.
+                        */
+                       c2->reset_group = true;
                }
        }
        return leader;
index 3655b9e..f5bd5c3 100644 (file)
@@ -334,9 +334,17 @@ void perf_evlist__to_front(struct evlist *evlist,
 #define evlist__for_each_entry_safe(evlist, tmp, evsel) \
        __evlist__for_each_entry_safe(&(evlist)->core.entries, tmp, evsel)
 
+#define evlist__for_each_cpu(evlist, index, cpu)       \
+       evlist__cpu_iter_start(evlist);                 \
+       perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
+
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel);
 
+void evlist__cpu_iter_start(struct evlist *evlist);
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu);
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu);
+
 struct evsel *
 perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str);
 
@@ -348,5 +356,6 @@ bool perf_evlist__exclude_kernel(struct evlist *evlist);
 void perf_evlist__force_leader(struct evlist *evlist);
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist,
-                                                struct evsel *evsel);
+                                                struct evsel *evsel,
+                                               bool close);
 #endif /* __PERF_EVLIST_H */
index f4dea05..a69e642 100644 (file)
@@ -1223,16 +1223,27 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter)
        return perf_evsel__append_filter(evsel, "%s,%s", filter);
 }
 
+/* Caller has to clear disabled after going through all CPUs. */
+int evsel__enable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__enable_cpu(&evsel->core, cpu);
+}
+
 int evsel__enable(struct evsel *evsel)
 {
        int err = perf_evsel__enable(&evsel->core);
 
        if (!err)
                evsel->disabled = false;
-
        return err;
 }
 
+/* Caller has to set disabled after going through all CPUs. */
+int evsel__disable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__disable_cpu(&evsel->core, cpu);
+}
+
 int evsel__disable(struct evsel *evsel)
 {
        int err = perf_evsel__disable(&evsel->core);
@@ -1587,8 +1598,9 @@ static int perf_event_open(struct evsel *evsel,
        return fd;
 }
 
-int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
-               struct perf_thread_map *threads)
+static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads,
+               int start_cpu, int end_cpu)
 {
        int cpu, thread, nthreads;
        unsigned long flags = PERF_FLAG_FD_CLOEXEC;
@@ -1665,7 +1677,7 @@ retry_sample_id:
 
        display_attr(&evsel->core.attr);
 
-       for (cpu = 0; cpu < cpus->nr; cpu++) {
+       for (cpu = start_cpu; cpu < end_cpu; cpu++) {
 
                for (thread = 0; thread < nthreads; thread++) {
                        int fd, group_fd;
@@ -1843,6 +1855,12 @@ out_close:
        return err;
 }
 
+int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads)
+{
+       return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1);
+}
+
 void evsel__close(struct evsel *evsel)
 {
        perf_evsel__close(&evsel->core);
@@ -1850,9 +1868,14 @@ void evsel__close(struct evsel *evsel)
 }
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus)
+                            struct perf_cpu_map *cpus,
+                            int cpu)
 {
-       return evsel__open(evsel, cpus, NULL);
+       if (cpu == -1)
+               return evsel__open_cpu(evsel, cpus, NULL, 0,
+                                       cpus ? cpus->nr : 1);
+
+       return evsel__open_cpu(evsel, cpus, NULL, cpu, cpu + 1);
 }
 
 int perf_evsel__open_per_thread(struct evsel *evsel,
index ddc5ee6..dc14f4a 100644 (file)
@@ -86,6 +86,7 @@ struct evsel {
        struct list_head        config_terms;
        struct bpf_object       *bpf_obj;
        int                     bpf_fd;
+       int                     err;
        bool                    auto_merge_stats;
        bool                    merged_stat;
        const char *            metric_expr;
@@ -94,7 +95,10 @@ struct evsel {
        struct evsel            *metric_leader;
        bool                    collect_stat;
        bool                    weak_group;
+       bool                    reset_group;
+       bool                    errored;
        bool                    percore;
+       int                     cpu_iter;
        const char              *pmu_name;
        struct {
                perf_evsel__sb_cb_t     *cb;
@@ -218,11 +222,14 @@ int perf_evsel__set_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_addr_filter(struct evsel *evsel,
                                   const char *filter);
+int evsel__enable_cpu(struct evsel *evsel, int cpu);
 int evsel__enable(struct evsel *evsel);
 int evsel__disable(struct evsel *evsel);
+int evsel__disable_cpu(struct evsel *evsel, int cpu);
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus);
+                            struct perf_cpu_map *cpus,
+                            int cpu);
 int perf_evsel__open_per_thread(struct evsel *evsel,
                                struct perf_thread_map *threads);
 int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
index f9f18b8..aed4980 100644 (file)
@@ -8,15 +8,12 @@
  */
 
 #include <sys/types.h>
-#include <stdio.h>
-#include <getopt.h>
 #include <stddef.h>
 #include <libelf.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <limits.h>
 #include <fcntl.h>
 #include <err.h>
 #ifdef HAVE_DWARF_SUPPORT
@@ -31,8 +28,6 @@
 #define NT_GNU_BUILD_ID 3
 #endif
 
-#define JVMTI
-
 #define BUILD_ID_URANDOM /* different uuid for each run */
 
 #ifdef HAVE_LIBCRYPTO
@@ -511,44 +506,3 @@ error:
 
        return retval;
 }
-
-#ifndef JVMTI
-
-static unsigned char x86_code[] = {
-    0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
-    0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
-    0xCD, 0x80            /* int $0x80 */
-};
-
-static struct options options;
-
-int main(int argc, char **argv)
-{
-       int c, fd, ret;
-
-       while ((c = getopt(argc, argv, "o:h")) != -1) {
-               switch (c) {
-               case 'o':
-                       options.output = optarg;
-                       break;
-               case 'h':
-                       printf("Usage: genelf -o output_file [-h]\n");
-                       return 0;
-               default:
-                       errx(1, "unknown option");
-               }
-       }
-
-       fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666);
-       if (fd == -1)
-               err(1, "cannot create file %s", options.output);
-
-       ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code));
-       close(fd);
-
-       if (ret != 0)
-               unlink(options.output);
-
-       return ret;
-}
-#endif
index becc2d1..93ad278 100644 (file)
@@ -850,7 +850,7 @@ int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
  */
 int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
 {
-       return -1;
+       return ENOSYS; /* Not implemented */
 }
 
 static int write_cpuid(struct feat_fd *ff,
@@ -1089,21 +1089,18 @@ static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
        fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
 }
 
-static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
+#define MAX_CACHE_LVL 4
+
+static int build_caches(struct cpu_cache_level caches[], u32 *cntp)
 {
        u32 i, cnt = 0;
-       long ncpus;
        u32 nr, cpu;
        u16 level;
 
-       ncpus = sysconf(_SC_NPROCESSORS_CONF);
-       if (ncpus < 0)
-               return -1;
-
-       nr = (u32)(ncpus & UINT_MAX);
+       nr = cpu__max_cpu();
 
        for (cpu = 0; cpu < nr; cpu++) {
-               for (level = 0; level < 10; level++) {
+               for (level = 0; level < MAX_CACHE_LVL; level++) {
                        struct cpu_cache_level c;
                        int err;
 
@@ -1123,18 +1120,12 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
                                caches[cnt++] = c;
                        else
                                cpu_cache_level__free(&c);
-
-                       if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
-                               goto out;
                }
        }
- out:
        *cntp = cnt;
        return 0;
 }
 
-#define MAX_CACHE_LVL 4
-
 static int write_cache(struct feat_fd *ff,
                       struct evlist *evlist __maybe_unused)
 {
@@ -1143,7 +1134,7 @@ static int write_cache(struct feat_fd *ff,
        u32 cnt = 0, i, version = 1;
        int ret;
 
-       ret = build_caches(caches, max_caches, &cnt);
+       ret = build_caches(caches, &cnt);
        if (ret)
                goto out;
 
index f01d48a..b8a5159 100644 (file)
@@ -5,10 +5,93 @@
 
 /* linkage.h ... for including arch/x86/lib/memcpy_64.S */
 
-#define ENTRY(name)                            \
-       .globl name;                            \
+/* Some toolchains use other characters (e.g. '`') to mark new line in macro */
+#ifndef ASM_NL
+#define ASM_NL          ;
+#endif
+
+#ifndef __ALIGN
+#define __ALIGN                .align 4,0x90
+#define __ALIGN_STR    ".align 4,0x90"
+#endif
+
+/* SYM_T_FUNC -- type used by assembler to mark functions */
+#ifndef SYM_T_FUNC
+#define SYM_T_FUNC                             STT_FUNC
+#endif
+
+/* SYM_A_* -- align the symbol? */
+#define SYM_A_ALIGN                            ALIGN
+
+/* SYM_L_* -- linkage of symbols */
+#define SYM_L_GLOBAL(name)                     .globl name
+#define SYM_L_LOCAL(name)                      /* nothing */
+
+#define ALIGN __ALIGN
+
+/* === generic annotations === */
+
+/* SYM_ENTRY -- use only if you have to for non-paired symbols */
+#ifndef SYM_ENTRY
+#define SYM_ENTRY(name, linkage, align...)             \
+       linkage(name) ASM_NL                            \
+       align ASM_NL                                    \
        name:
+#endif
+
+/* SYM_START -- use only if you have to */
+#ifndef SYM_START
+#define SYM_START(name, linkage, align...)             \
+       SYM_ENTRY(name, linkage, align)
+#endif
+
+/* SYM_END -- use only if you have to */
+#ifndef SYM_END
+#define SYM_END(name, sym_type)                                \
+       .type name sym_type ASM_NL                      \
+       .size name, .-name
+#endif
+
+/*
+ * SYM_FUNC_START_ALIAS -- use where there are two global names for one
+ * function
+ */
+#ifndef SYM_FUNC_START_ALIAS
+#define SYM_FUNC_START_ALIAS(name)                     \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START -- use for global functions */
+#ifndef SYM_FUNC_START
+/*
+ * The same as SYM_FUNC_START_ALIAS, but we will need to distinguish these two
+ * later.
+ */
+#define SYM_FUNC_START(name)                           \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START_LOCAL -- use for local functions */
+#ifndef SYM_FUNC_START_LOCAL
+/* the same as SYM_FUNC_START_LOCAL_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_START_LOCAL(name)                     \
+       SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_END_ALIAS -- the end of LOCAL_ALIASed or ALIASed function */
+#ifndef SYM_FUNC_END_ALIAS
+#define SYM_FUNC_END_ALIAS(name)                       \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
-#define ENDPROC(name)
+/*
+ * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START,
+ * SYM_FUNC_START_WEAK, ...
+ */
+#ifndef SYM_FUNC_END
+/* the same as SYM_FUNC_END_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_END(name)                             \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
 #endif /* PERF_LINUX_LINKAGE_H_ */
index 416d174..c8c5410 100644 (file)
@@ -2446,6 +2446,7 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms
 
        list_for_each_entry(ilist, &inline_node->val, list) {
                struct map_symbol ilist_ms = {
+                       .maps = ms->maps,
                        .map = map,
                        .sym = ilist->symbol,
                };
index 6a4d350..02aee94 100644 (file)
@@ -103,8 +103,11 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                if (!strcmp(ev->name, ids[i])) {
                        if (!metric_events[i])
                                metric_events[i] = ev;
+                       i++;
+                       if (i == idnum)
+                               break;
                } else {
-                       if (++i == idnum) {
+                       if (i + 1 == idnum) {
                                /* Discard the whole match and start again */
                                i = 0;
                                memset(metric_events, 0,
@@ -124,7 +127,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                }
        }
 
-       if (i != idnum - 1) {
+       if (i != idnum) {
                /* Not whole match */
                return NULL;
        }
index 345b5cc..9fcba28 100644 (file)
@@ -2681,12 +2681,12 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
                        ret = sort_dimension__add(list, tok, evlist, level);
                        if (ret == -EINVAL) {
                                if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok)))
-                                       pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
+                                       ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
                                else
-                                       pr_err("Invalid --sort key: `%s'", tok);
+                                       ui__error("Invalid --sort key: `%s'", tok);
                                break;
                        } else if (ret == -ESRCH) {
-                               pr_err("Unknown --sort key: `%s'", tok);
+                               ui__error("Unknown --sort key: `%s'", tok);
                                break;
                        }
                }
@@ -2743,7 +2743,7 @@ static int setup_sort_order(struct evlist *evlist)
                return 0;
 
        if (sort_order[1] == '\0') {
-               pr_err("Invalid --sort key: `+'");
+               ui__error("Invalid --sort key: `+'");
                return -EINVAL;
        }
 
@@ -2959,6 +2959,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__MEMORY)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -2968,6 +2971,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__BRANCH)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -3034,7 +3040,7 @@ static int __setup_output_field(void)
                strp++;
 
        if (!strlen(strp)) {
-               pr_err("Invalid --fields key: `+'");
+               ui__error("Invalid --fields key: `+'");
                goto out;
        }
 
index 332cb73..5f26137 100644 (file)
@@ -464,7 +464,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target)
+                            struct target *target,
+                            int cpu)
 {
        struct perf_event_attr *attr = &evsel->core.attr;
        struct evsel *leader = evsel->leader;
@@ -518,7 +519,7 @@ int create_perf_stat_counter(struct evsel *evsel,
        }
 
        if (target__has_cpu(target) && !target__has_per_thread(target))
-               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel));
+               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu);
 
        return perf_evsel__open_per_thread(evsel, evsel->core.threads);
 }
index bfa9aaf..fb990ef 100644 (file)
@@ -214,7 +214,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target);
+                            struct target *target,
+                            int cpu);
 void
 perf_evlist__print_counters(struct evlist *evlist,
                            struct perf_stat_config *config,
index 4a12baa..a2a8ea6 100755 (executable)
@@ -199,7 +199,7 @@ class KUnitMainTest(unittest.TestCase):
                timeout = 3453
                kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
                assert self.linux_source_mock.build_reconfig.call_count == 1
-               self.linux_source_mock.run_kernel.assert_called_once_with(timeout=timeout)
+               self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=None, timeout=timeout)
                self.print_mock.assert_any_call(StrContains('Testing complete.'))
 
 if __name__ == '__main__':
index 36fb59f..1a52f28 100644 (file)
@@ -3,6 +3,8 @@
 # description: ftrace - stacktrace filter command
 # flags: instance
 
+[ ! -f set_ftrace_filter ] && exit_unsupported
+
 echo _do_fork:stacktrace >> set_ftrace_filter
 
 grep -q "_do_fork:stacktrace:unlimited" set_ftrace_filter
index 86a1f07..71fa3f4 100644 (file)
@@ -15,6 +15,11 @@ if [ $NP -eq 1 ] ;then
   exit_unresolved
 fi
 
+if ! grep -q "function" available_tracers ; then
+  echo "Function trace is not enabled"
+  exit_unsupported
+fi
+
 ORIG_CPUMASK=`cat tracing_cpumask`
 
 do_reset() {
index 86986c4..5d45505 100644 (file)
@@ -46,6 +46,9 @@ reset_events_filter() { # reset all current setting filters
 }
 
 reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
+    if [ ! -f set_ftrace_filter ]; then
+      return 0
+    fi
     echo > set_ftrace_filter
     grep -v '^#' set_ftrace_filter | while read t; do
        tr=`echo $t | cut -d: -f2`
@@ -93,7 +96,7 @@ initialize_ftrace() { # Reset ftrace to initial-state
     disable_events
     [ -f set_event_pid ] && echo > set_event_pid
     [ -f set_ftrace_pid ] && echo > set_ftrace_pid
-    [ -f set_ftrace_filter ] && echo | tee set_ftrace_*
+    [ -f set_ftrace_notrace ] && echo > set_ftrace_notrace
     [ -f set_graph_function ] && echo | tee set_graph_*
     [ -f stack_trace_filter ] && echo > stack_trace_filter
     [ -f kprobe_events ] && echo > kprobe_events
index 5862eee..6e3dbe5 100644 (file)
@@ -20,9 +20,9 @@ while read i; do
   test $N -eq 256 && break
 done
 
-L=`wc -l kprobe_events`
-if [ $L -ne $N ]; then
-  echo "The number of kprobes events ($L) is not $N"
+L=`cat kprobe_events | wc -l`
+if [ $L -ne 256 ]; then
+  echo "The number of kprobes events ($L) is not 256"
   exit_fail
 fi
 
index 1221240..3f2aee1 100644 (file)
@@ -21,10 +21,10 @@ grep -q "snapshot()" README || exit_unsupported # version issue
 
 echo "Test expected snapshot action failure"
 
-echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail
+echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> events/sched/sched_waking/trigger && exit_fail
 
 echo "Test expected save action failure"
 
-echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail
+echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> events/sched/sched_waking/trigger && exit_fail
 
 exit_xfail
index 064a284..c80007a 100644 (file)
@@ -16,7 +16,7 @@ grep -q "onchange(var)" README || exit_unsupported # version issue
 
 echo "Test onchange action"
 
-echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger
+echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> events/sched/sched_waking/trigger
 
 ping $LOCALHOST -c 3
 nice -n 1 ping $LOCALHOST -c 3
index 18fff69..f546c1b 100644 (file)
@@ -23,9 +23,9 @@ grep -q "snapshot()" README || exit_unsupported # version issue
 
 echo "Test snapshot action"
 
-echo 1 > /sys/kernel/debug/tracing/events/sched/enable
+echo 1 > events/sched/enable
 
-echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger
+echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> events/sched/sched_waking/trigger
 
 ping $LOCALHOST -c 3
 nice -n 1 ping $LOCALHOST -c 3
index 18e1c79..fb4733f 100755 (executable)
@@ -9,7 +9,7 @@
 #
 #   #!/bin/sh
 #   SPDX-License-Identifier: GPL-2.0+
-#   $(dirname $0)/../kselftest_module.sh "description" module_name
+#   $(dirname $0)/../kselftest/module.sh "description" module_name
 #
 # Example: tools/testing/selftests/lib/printf.sh
 
index ec7e481..31f7c2a 100755 (executable)
@@ -3,6 +3,7 @@
 # Prefix all lines with "# ", unbuffered. Command being piped in may need
 # to have unbuffering forced with "stdbuf -i0 -o0 -e0 $cmd".
 use strict;
+use IO::Handle;
 
 binmode STDIN;
 binmode STDOUT;
index 84de7bc..a8d20cb 100644 (file)
@@ -79,6 +79,7 @@ run_one()
                if [ $rc -eq $skip_rc ]; then   \
                        echo "not ok $test_num $TEST_HDR_MSG # SKIP"
                elif [ $rc -eq $timeout_rc ]; then \
+                       echo "#"
                        echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT"
                else
                        echo "not ok $test_num $TEST_HDR_MSG # exit=$rc"
index 98da7a5..fa02c4d 100644 (file)
@@ -1,8 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for mount selftests.
-CFLAGS = -Wall -lcap -O2
+CFLAGS = -Wall -O2
+LDLIBS = -lcap
 
-TEST_PROGS := run_tests.sh
+TEST_PROGS := safesetid-test.sh
 TEST_GEN_FILES := safesetid-test
 
 include ../lib.mk
index 8f40c6e..0c4d506 100644 (file)
@@ -213,7 +213,8 @@ static void test_setuid(uid_t child_uid, bool expect_success)
        }
 
        if (cpid == 0) {            /* Code executed by child */
-               setuid(child_uid);
+               if (setuid(child_uid) < 0)
+                       exit(EXIT_FAILURE);
                if (getuid() == child_uid)
                        exit(EXIT_SUCCESS);
                else
@@ -291,8 +292,10 @@ int main(int argc, char **argv)
 
        // First test to make sure we can write userns mappings from a user
        // that doesn't have any restrictions (as long as it has CAP_SETUID);
-       setuid(NO_POLICY_USER);
-       setgid(NO_POLICY_USER);
+       if (setuid(NO_POLICY_USER) < 0)
+               die("Error with set uid(%d)\n", NO_POLICY_USER);
+       if (setgid(NO_POLICY_USER) < 0)
+               die("Error with set gid(%d)\n", NO_POLICY_USER);
 
        // Take away all but setid caps
        drop_caps(true);
@@ -306,8 +309,10 @@ int main(int argc, char **argv)
                die("test_userns failed when it should work\n");
        }
 
-       setuid(RESTRICTED_PARENT);
-       setgid(RESTRICTED_PARENT);
+       if (setuid(RESTRICTED_PARENT) < 0)
+               die("Error with set uid(%d)\n", RESTRICTED_PARENT);
+       if (setgid(RESTRICTED_PARENT) < 0)
+               die("Error with set gid(%d)\n", RESTRICTED_PARENT);
 
        test_setuid(ROOT_USER, false);
        test_setuid(ALLOWED_CHILD1, true);
index 80521d4..8155c2e 100755 (executable)
@@ -2,3 +2,9 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
 python -m unittest -v tpm2_tests.SmokeTest
+python -m unittest -v tpm2_tests.AsyncTest
+
+CLEAR_CMD=$(which tpm2_clear)
+if [ -n $CLEAR_CMD ]; then
+       tpm2_clear -T device
+fi
index 828c185..d0fcb66 100644 (file)
@@ -6,8 +6,8 @@ import socket
 import struct
 import sys
 import unittest
-from fcntl import ioctl
-
+import fcntl
+import select
 
 TPM2_ST_NO_SESSIONS = 0x8001
 TPM2_ST_SESSIONS = 0x8002
@@ -352,6 +352,7 @@ def hex_dump(d):
 class Client:
     FLAG_DEBUG = 0x01
     FLAG_SPACE = 0x02
+    FLAG_NONBLOCK = 0x04
     TPM_IOC_NEW_SPACE = 0xa200
 
     def __init__(self, flags = 0):
@@ -362,13 +363,27 @@ class Client:
         else:
             self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
 
+        if (self.flags & Client.FLAG_NONBLOCK):
+            flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)
+            flags |= os.O_NONBLOCK
+            fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)
+            self.tpm_poll = select.poll()
+
     def close(self):
         self.tpm.close()
 
     def send_cmd(self, cmd):
         self.tpm.write(cmd)
+
+        if (self.flags & Client.FLAG_NONBLOCK):
+            self.tpm_poll.register(self.tpm, select.POLLIN)
+            self.tpm_poll.poll(10000)
+
         rsp = self.tpm.read()
 
+        if (self.flags & Client.FLAG_NONBLOCK):
+            self.tpm_poll.unregister(self.tpm)
+
         if (self.flags & Client.FLAG_DEBUG) != 0:
             sys.stderr.write('cmd' + os.linesep)
             sys.stderr.write(hex_dump(cmd) + os.linesep)
index d4973be..728be7c 100644 (file)
@@ -288,3 +288,16 @@ class SpaceTest(unittest.TestCase):
 
         self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE |
                          tpm2.TSS2_RESMGR_TPM_RC_LAYER)
+
+class AsyncTest(unittest.TestCase):
+    def setUp(self):
+        logging.basicConfig(filename='AsyncTest.log', level=logging.DEBUG)
+
+    def test_async(self):
+        log = logging.getLogger(__name__)
+        log.debug(sys._getframe().f_code.co_name)
+
+        async_client = tpm2.Client(tpm2.Client.FLAG_NONBLOCK)
+        log.debug("Calling get_cap in a NON_BLOCKING mode")
+        async_client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION)
+        async_client.close()