]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Dec 2019 17:54:33 +0000 (09:54 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Dec 2019 17:54:33 +0000 (09:54 -0800)
Pull networking fixes from David Miller:

 1) Several nf_flow_table_offload fixes from Pablo Neira Ayuso,
    including adding a missing ipv6 match description.

 2) Several heap overflow fixes in mwifiex from qize wang and Ganapathi
    Bhat.

 3) Fix uninit value in bond_neigh_init(), from Eric Dumazet.

 4) Fix non-ACPI probing of nxp-nci, from Stephan Gerhold.

 5) Fix use after free in tipc_disc_rcv(), from Tuong Lien.

 6) Enforce limit of 33 tail calls in mips and riscv JIT, from Paul
    Chaignon.

 7) Multicast MAC limit test is off by one in qede, from Manish Chopra.

 8) Fix established socket lookup race when socket goes from
    TCP_ESTABLISHED to TCP_LISTEN, because there lacks an intervening
    RCU grace period. From Eric Dumazet.

 9) Don't send empty SKBs from tcp_write_xmit(), also from Eric Dumazet.

10) Fix active backup transition after link failure in bonding, from
    Mahesh Bandewar.

11) Avoid zero sized hash table in gtp driver, from Taehee Yoo.

12) Fix wrong interface passed to ->mac_link_up(), from Russell King.

13) Fix DSA egress flooding settings in b53, from Florian Fainelli.

14) Memory leak in gmac_setup_txqs(), from Navid Emamdoost.

15) Fix double free in dpaa2-ptp code, from Ioana Ciornei.

16) Reject invalid MTU values in stmmac, from Jose Abreu.

17) Fix refcount leak in error path of u32 classifier, from Davide
    Caratti.

18) Fix regression causing iwlwifi firmware crashes on boot, from Anders
    Kaseorg.

19) Fix inverted return value logic in llc2 code, from Chan Shu Tak.

20) Disable hardware GRO when XDP is attached to qede, frm Manish
    Chopra.

21) Since we encode state in the low pointer bits, dst metrics must be
    at least 4 byte aligned, which is not necessarily true on m68k. Add
    annotations to fix this, from Geert Uytterhoeven.

* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (160 commits)
  sfc: Include XDP packet headroom in buffer step size.
  sfc: fix channel allocation with brute force
  net: dst: Force 4-byte alignment of dst_metrics
  selftests: pmtu: fix init mtu value in description
  hv_netvsc: Fix unwanted rx_table reset
  net: phy: ensure that phy IDs are correctly typed
  mod_devicetable: fix PHY module format
  qede: Disable hardware gro when xdp prog is installed
  net: ena: fix issues in setting interrupt moderation params in ethtool
  net: ena: fix default tx interrupt moderation interval
  net/smc: unregister ib devices in reboot_event
  net: stmmac: platform: Fix MDIO init for platforms without PHY
  llc2: Fix return statement of llc_stat_ev_rx_null_dsap_xid_c (and _test_c)
  net: hisilicon: Fix a BUG trigered by wrong bytes_compl
  net: dsa: ksz: use common define for tag len
  s390/qeth: don't return -ENOTSUPP to userspace
  s390/qeth: fix promiscuous mode after reset
  s390/qeth: handle error due to unsupported transport mode
  cxgb4: fix refcount init for TC-MQPRIO offload
  tc-testing: initial tdc selftests for cls_u32
  ...

751 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 [new file with mode: 0644]
Documentation/filesystems/overlayfs.txt [deleted file]
Documentation/kbuild/kconfig-language.rst
Documentation/kbuild/makefiles.rst
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/timex.h
arch/s390/include/asm/uv.h
arch/s390/kernel/early.c
arch/s390/kernel/mcount.S
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/smp.c
arch/s390/kernel/unwind_bc.c
arch/s390/lib/spinlock.c
arch/s390/lib/test_unwind.c
arch/s390/mm/kasan_init.c
arch/s390/purgatory/.gitignore
arch/s390/purgatory/Makefile
arch/s390/purgatory/string.c [new file with mode: 0644]
arch/sh/drivers/platform_early.c
arch/sh/kernel/kgdb.c
arch/sparc/net/bpf_jit_comp_32.c
arch/x86/boot/compressed/Makefile
arch/x86/events/core.c
arch/x86/events/intel/bts.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/events/core.c
kernel/locking/mutex.c
kernel/locking/spinlock_debug.c
kernel/module.c
kernel/sched/cpufreq.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/trace/fgraph.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_inject.c
kernel/trace/tracing_map.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
samples/trace_printk/trace-printk.c
scripts/checkpatch.pl
scripts/kallsyms.c
scripts/kconfig/expr.c
scripts/mkcompile_h
scripts/package/mkdebian
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/nvdimm/Kbuild
tools/testing/nvdimm/test/iomap.c
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
usr/include/Makefile

index d33bb3a3b70a57b3fb07f3ca4b64dfc0c3d3afd0..a7bc8cabd157b89adbc2d8f6c4d6e3c88b14e3cd 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>
@@ -277,3 +278,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 c65a8057486921ae53d505c7a03f0a76333c5bed..401d202f478b230014ce7a6ee247cbea76dc45da 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 594095b54b296567d09d1650d281b5a7e4f44c1f..c00f9f11e3f3f6133d4b741244e034ae2a3c430e 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 4872fb6d29524593849fbe68491e372d0901dfc3..ec62fcc8eeceed83a1cfd3020ff87595affc6ad0 100644 (file)
@@ -8,6 +8,7 @@ Device Mapper
     cache-policies
     cache
     delay
+    dm-clone
     dm-crypt
     dm-dust
     dm-flakey
index ecdfdc9d4b0320f9ea4fb51974bfd5e35dfa36e0..61ae13c44f915db2b8339541798eb0266e10e3d4 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 26ffb46bdf99d0382d29bde9173c75a61b74deee..c60d760a0eed1f732cca2fd3c51075368a0ce24f 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 aeeddfafeea20befae5a3c28b25f207f226d78fa..9d6db892c41c04d711289eb696216d667da12319 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 c6e69634e274b40b617b23d539734d344b6c88ae..b9a065ab681eeae52d21463daa12d03c633603bd 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 8a1e38a1d7ab196debe1feb614109598a35928f0..cffe8bb0bad106b35586956649dab8476e2fa5a8 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 d2a872286437e4c65c12f94f506283aed588bd4b..f0b3d30fbb76f7401b3f41b2d583b05de58fe278 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 be32f087c529303e02db711f4d88a5f44f33be6d..9fe11ceecdba004c5546f30711be002eaca64694 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 64938fdaea554973d960bd1c3b4f01e130747167..4d382128b711c8cace6414831a0a6ff07238a77e 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 80b3e7350a732b8e2fbe4ab39a9a99f7b539bc28..33c7842917f629c8176df1f94ad52e4fc629a271 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 dafc0980c4fa7a241722430c6df62f4f331d1601..0f7074977c04d836a329e147847ceda0d5c46249 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 0e7987f1cdb799ad01257b445b25f21876ffe65f..d67617f6f74ab10eabd05a1830e9ac448c113f69 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 15abc0f9429fcd8b813d620d8e8a0f115b70a6de..83808199657b731544c5fd0059b9f6639bcdf92b 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 387d599522c708eaef3a201f8afbf7382c88aab2..9e53472be1947d0dcf4aa0fc26ab32f6b6c8031f 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 740b7f9b535b29267d834e35181d9782f24b5280..c1676b96daac7e13d370c7c1f32a71f4ea7df3cb 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 9346ef6ba61b681e0dd303d58ade4a252a3594cb..6097e8ac46c1f5a9cfdfdb503b92380f28e2cf46 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 b68be3aaf587c94401783878d9a21fc809ef7c3b..e1f6d64bdccd188497b33b67ab744293810bfab0 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 d74962c0f5ae367a8a023a24277b356f5e9b317e..15c514b83583b81cce8ac27bda28d5be6b65bab9 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 b3bd8ef7fbd6101bc110fbd5cc101e9e865d8465..5b3b71c9c0183ccfe8eb00649de1d4ad7e5fdaf4 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 23a202d24e437bc8c0c098c28a22e5f55d37ba06..953d875b5e74aab183787caf6aec267b9a9e7322 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 8cd08cfb25bef7e1b1388e898bb51f97e8469086..cf09055da78b2c95a3548860e2bd04d179e33570 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 d3e423fcb6c2ee643529f67527eda8ba88c3d32c..0f6374ceaa697164fe55f58185ec0eeb99c0cc36 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 dea36d68cdbedf312ee80ea5d7e5a50e1bb3f427..7838804700d66a2bfa7661280bd96ce65b7308fd 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 30d9fb193d7fce7a6d550a165b4842a24783a891..22a94b6fdbdee478366360a412dbc54ced745071 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 7fe0ca14e324f3afe603dba11c704dc961590383..e4135bac6957344b36aa42664d6c723448b66aa8 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 84fd57bcf0dcd723e73f8182f718f23c717b8804..4b9196c832915f08adde760272762b7a83f73dbc 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 4b1a09acb98b7e59c61437221d95e2e2fff3c4d1..39afacc447b208f149d8b0ef9cb2ab981be633e2 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 64bca41031d513d2e766fff40ded84961239d82b..e82c9a07b6fb020f773984b3b50754af2d6f2780 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 b5b3cf5b1ac236770c0a741c934f6edea65dee00..5d3fa412aabd3f91b12463af68990517e3466df5 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 ae4796ec50a0a6612bfc26e70b898d1237713971..8d8560a67abf2750787afa144c06c2e43b702a62 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 e5562c525ed94baecc2ef24f7b313b01fb1e8a76..767193ec1d3285ec0ebe71a505c543c92c876de9 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 f683b7104e3eb424092324a4ea5783b1b59a15c9..703d0d8868846dde2ce14a0fafef6acd264bce28 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 11654d4b80fb7616c73c81660dec001729b9806f..db36b4d8648449927a419961e7308c2151582a76 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 770af7c46114024880da0f5d0e137296b7546b69..a95960ee3feba1077ae7ed0aa6c4d43c8d6e5467 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 4845e29411e460151458a97a39256cff9deff8e7..e08cd4c4d5682f7e7e7b53df24c6b36891d28226 100644 (file)
@@ -347,6 +347,7 @@ allOf:
               - st,spear600-gmac
 
     then:
+      properties:
         snps,tso:
           $ref: /schemas/types.yaml#definitions/flag
           description:
index 81ae8cafabc1444b584d8cfc393b433287fbe2ff..ac8c76369a867b55e37a01fa51446e611889c13f 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 659b02002a35c24148cad4dbdf12e43627a19143..daf1321d76ad8356bd7f636ad4c101e39a102549 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 fa46670de2992dd1bde4809e397a905e8f77e72f..230d74f22136c6cee6d6170627e6e982858a3e50 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 cd0503b6fe36fff23f47ab53c03da3b8ab534257..bfefd09d8c1e43ab3abba75930decf004b7a95af 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 0ac52f83a58cce4f222f20a266fc2d4528416284..4a21fe77ee1d34e650183704b671b74de222e23c 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 acf18d170352d242812d43338974a92ff85d7c93..c0d83865e933a2cbe896c5ae847ee7640cbc5637 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 6e5341b4f8919ecda07304b5a2406f33ffa2c00f..ee59409640f244ebf5d985c18f46d91d3fbd9f6a 100644 (file)
@@ -22,6 +22,6 @@ Example:
        };
 
        &ethernet_switch {
-               resets = <&reset>;
+               resets = <&reset 26>;
                reset-names = "switch";
        };
index 46d69c32b89b89506f28a3a73dc1803fa9490a21..478b0234e8fa97416db572c50ce58fed4c5b88c7 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 d7a57ec4a6400bec0f0107fb1aeba516a1175bb1..37c2a601c3fa8ab075cbc2a7817876386a0600f3 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 ee9712f1c97d44b23bd2cf61b0cbe0c60f7b85fe..2ecab8ed702a20abfa5d1e44b89e267852df1c06 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 b8f89c7258ebc853a1c416a75c8dc08f634aa8aa..ea1d2efb2aaa36d79790132db1ad6a170a55220e 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 eb3992138eecce3cf0283754b9c47a9ab6f8f4ee..112ae00d63c1d6576583b1542705b6a8a7ef500b 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 38d4cede0860dd5aed5402e4cdb34dff5f39a677..444a432912bb4ec7970a2a61e26e33b2b09fac24 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 f290eb72a8781e7b0f2138ac74271cd087583716..3b764415c9abf7a696c7f965cbb36abfac4264d0 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 85305b4c2729b74759d319eef9ac5d9cb88234e7..9718358826abdaebd02260385519c7a5b7d34898 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 5e7cc05bbff1dc5f3705b58930f3674f89e67e15..55d28268d2f4ff5c0860b02609185311b42b90ce 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 6d1329c281707fbefe0aa403b860c6105d5a4a71..8036499112f5a858e00f8edf0fa425eacf7db76f 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 f36c46d236d7a6afdf82ee2a7af704ecbf68e1a6..0565dc49e44940dc6326f2ee2c1672542df653d2 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 20adc1c8e9cccb33a94f385966c02df961f0fa59..23e989e0976630382d70ab5ddaeeb3b4c3542b61 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 dfa0c41fd261d166b95af163f195f45358798bc8..40fc4bcb31457db7374f4266839894469cd2366f 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 0af70fc8de5a764003f08e6cf940f52d4d84c86b..d9207bf9d8946e4ee9c799f1adc92ec5906d0359 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 3a54f58683a0ed01292c43b2554f63d295461a5d..e8f226376108178037de849d474715ce2d6d678c 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 b0c085326e2e68f4ead9063af48beeda0b48dcf9..db6d39c3ae715ee90b876c4660346581f3b67171 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
diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
new file mode 100644 (file)
index 0000000..e443be7
--- /dev/null
@@ -0,0 +1,497 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Written by: Neil Brown
+Please see MAINTAINERS file for where to send questions.
+
+Overlay Filesystem
+==================
+
+This document describes a prototype for a new approach to providing
+overlay-filesystem functionality in Linux (sometimes referred to as
+union-filesystems).  An overlay-filesystem tries to present a
+filesystem which is the result over overlaying one filesystem on top
+of the other.
+
+
+Overlay objects
+---------------
+
+The overlay filesystem approach is 'hybrid', because the objects that
+appear in the filesystem do not always appear to belong to that filesystem.
+In many cases, an object accessed in the union will be indistinguishable
+from accessing the corresponding object from the original filesystem.
+This is most obvious from the 'st_dev' field returned by stat(2).
+
+While directories will report an st_dev from the overlay-filesystem,
+non-directory objects may report an st_dev from the lower filesystem or
+upper filesystem that is providing the object.  Similarly st_ino will
+only be unique when combined with st_dev, and both of these can change
+over the lifetime of a non-directory object.  Many applications and
+tools ignore these values and will not be affected.
+
+In the special case of all overlay layers on the same underlying
+filesystem, all objects will report an st_dev from the overlay
+filesystem and st_ino from the underlying filesystem.  This will
+make the overlay mount more compliant with filesystem scanners and
+overlay objects will be distinguishable from the corresponding
+objects in the original filesystem.
+
+On 64bit systems, even if all overlay layers are not on the same
+underlying filesystem, the same compliant behavior could be achieved
+with the "xino" feature.  The "xino" feature composes a unique object
+identifier from the real object st_ino and an underlying fsid index.
+If all underlying filesystems support NFS file handles and export file
+handles with 32bit inode number encoding (e.g. ext4), overlay filesystem
+will use the high inode number bits for fsid.  Even when the underlying
+filesystem uses 64bit inode numbers, users can still enable the "xino"
+feature with the "-o xino=on" overlay mount option.  That is useful for the
+case of underlying filesystems like xfs and tmpfs, which use 64bit inode
+numbers, but are very unlikely to use the high inode number bit.
+
+
+Upper and Lower
+---------------
+
+An overlay filesystem combines two filesystems - an 'upper' filesystem
+and a 'lower' filesystem.  When a name exists in both filesystems, the
+object in the 'upper' filesystem is visible while the object in the
+'lower' filesystem is either hidden or, in the case of directories,
+merged with the 'upper' object.
+
+It would be more correct to refer to an upper and lower 'directory
+tree' rather than 'filesystem' as it is quite possible for both
+directory trees to be in the same filesystem and there is no
+requirement that the root of a filesystem be given for either upper or
+lower.
+
+The lower filesystem can be any filesystem supported by Linux and does
+not need to be writable.  The lower filesystem can even be another
+overlayfs.  The upper filesystem will normally be writable and if it
+is it must support the creation of trusted.* extended attributes, and
+must provide valid d_type in readdir responses, so NFS is not suitable.
+
+A read-only overlay of two read-only filesystems may use any
+filesystem type.
+
+Directories
+-----------
+
+Overlaying mainly involves directories.  If a given name appears in both
+upper and lower filesystems and refers to a non-directory in either,
+then the lower object is hidden - the name refers only to the upper
+object.
+
+Where both upper and lower objects are directories, a merged directory
+is formed.
+
+At mount time, the two directories given as mount options "lowerdir" and
+"upperdir" are combined into a merged directory:
+
+  mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
+  workdir=/work /merged
+
+The "workdir" needs to be an empty directory on the same filesystem
+as upperdir.
+
+Then whenever a lookup is requested in such a merged directory, the
+lookup is performed in each actual directory and the combined result
+is cached in the dentry belonging to the overlay filesystem.  If both
+actual lookups find directories, both are stored and a merged
+directory is created, otherwise only one is stored: the upper if it
+exists, else the lower.
+
+Only the lists of names from directories are merged.  Other content
+such as metadata and extended attributes are reported for the upper
+directory only.  These attributes of the lower directory are hidden.
+
+whiteouts and opaque directories
+--------------------------------
+
+In order to support rm and rmdir without changing the lower
+filesystem, an overlay filesystem needs to record in the upper filesystem
+that files have been removed.  This is done using whiteouts and opaque
+directories (non-directories are always opaque).
+
+A whiteout is created as a character device with 0/0 device number.
+When a whiteout is found in the upper level of a merged directory, any
+matching name in the lower level is ignored, and the whiteout itself
+is also hidden.
+
+A directory is made opaque by setting the xattr "trusted.overlay.opaque"
+to "y".  Where the upper filesystem contains an opaque directory, any
+directory in the lower filesystem with the same name is ignored.
+
+readdir
+-------
+
+When a 'readdir' request is made on a merged directory, the upper and
+lower directories are each read and the name lists merged in the
+obvious way (upper is read first, then lower - entries that already
+exist are not re-added).  This merged name list is cached in the
+'struct file' and so remains as long as the file is kept open.  If the
+directory is opened and read by two processes at the same time, they
+will each have separate caches.  A seekdir to the start of the
+directory (offset 0) followed by a readdir will cause the cache to be
+discarded and rebuilt.
+
+This means that changes to the merged directory do not appear while a
+directory is being read.  This is unlikely to be noticed by many
+programs.
+
+seek offsets are assigned sequentially when the directories are read.
+Thus if
+
+  - read part of a directory
+  - remember an offset, and close the directory
+  - re-open the directory some time later
+  - seek to the remembered offset
+
+there may be little correlation between the old and new locations in
+the list of filenames, particularly if anything has changed in the
+directory.
+
+Readdir on directories that are not merged is simply handled by the
+underlying directory (upper or lower).
+
+renaming directories
+--------------------
+
+When renaming a directory that is on the lower layer or merged (i.e. the
+directory was not created on the upper layer to start with) overlayfs can
+handle it in two different ways:
+
+1. return EXDEV error: this error is returned by rename(2) when trying to
+   move a file or directory across filesystem boundaries.  Hence
+   applications are usually prepared to hande this error (mv(1) for example
+   recursively copies the directory tree).  This is the default behavior.
+
+2. If the "redirect_dir" feature is enabled, then the directory will be
+   copied up (but not the contents).  Then the "trusted.overlay.redirect"
+   extended attribute is set to the path of the original location from the
+   root of the overlay.  Finally the directory is moved to the new
+   location.
+
+There are several ways to tune the "redirect_dir" feature.
+
+Kernel config options:
+
+- OVERLAY_FS_REDIRECT_DIR:
+    If this is enabled, then redirect_dir is turned on by  default.
+- OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW:
+    If this is enabled, then redirects are always followed by default. Enabling
+    this results in a less secure configuration.  Enable this option only when
+    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/):
+
+- "redirect_dir=BOOL":
+    See OVERLAY_FS_REDIRECT_DIR kernel config option above.
+- "redirect_always_follow=BOOL":
+    See OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW kernel config option above.
+- "redirect_max=NUM":
+    The maximum number of bytes in an absolute redirect (default is 256).
+
+Mount options:
+
+- "redirect_dir=on":
+    Redirects are enabled.
+- "redirect_dir=follow":
+    Redirects are not created, but followed.
+- "redirect_dir=off":
+    Redirects are not created and only followed if "redirect_always_follow"
+    feature is enabled in the kernel/module config.
+- "redirect_dir=nofollow":
+    Redirects are not created and not followed (equivalent to "redirect_dir=off"
+    if "redirect_always_follow" feature is not enabled).
+
+When the NFS export feature is enabled, every copied up directory is
+indexed by the file handle of the lower inode and a file handle of the
+upper directory is stored in a "trusted.overlay.upper" extended attribute
+on the index entry.  On lookup of a merged directory, if the upper
+directory does not match the file handle stores in the index, that is an
+indication that multiple upper directories may be redirected to the same
+lower directory.  In that case, lookup returns an error and warns about
+a possible inconsistency.
+
+Because lower layer redirects cannot be verified with the index, enabling
+NFS export support on an overlay filesystem with no upper layer requires
+turning off redirect follow (e.g. "redirect_dir=nofollow").
+
+
+Non-directories
+---------------
+
+Objects that are not directories (files, symlinks, device-special
+files etc.) are presented either from the upper or lower filesystem as
+appropriate.  When a file in the lower filesystem is accessed in a way
+the requires write-access, such as opening for write access, changing
+some metadata etc., the file is first copied from the lower filesystem
+to the upper filesystem (copy_up).  Note that creating a hard-link
+also requires copy_up, though of course creation of a symlink does
+not.
+
+The copy_up may turn out to be unnecessary, for example if the file is
+opened for read-write but the data is not modified.
+
+The copy_up process first makes sure that the containing directory
+exists in the upper filesystem - creating it and any parents as
+necessary.  It then creates the object with the same metadata (owner,
+mode, mtime, symlink-target etc.) and then if the object is a file, the
+data is copied from the lower to the upper filesystem.  Finally any
+extended attributes are copied up.
+
+Once the copy_up is complete, the overlay filesystem simply
+provides direct access to the newly created file in the upper
+filesystem - future operations on the file are barely noticed by the
+overlay filesystem (though an operation on the name of the file such as
+rename or unlink will of course be noticed and handled).
+
+
+Multiple lower layers
+---------------------
+
+Multiple lower layers can now be given using the the colon (":") as a
+separator character between the directory names.  For example:
+
+  mount -t overlay overlay -olowerdir=/lower1:/lower2:/lower3 /merged
+
+As the example shows, "upperdir=" and "workdir=" may be omitted.  In
+that case the overlay will be read-only.
+
+The specified lower directories will be stacked beginning from the
+rightmost one and going left.  In the above example lower1 will be the
+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
+like chown/chmod is performed. Full file will be copied up later when
+file is opened for WRITE operation.
+
+In other words, this is delayed data copy up operation and data is copied
+up when there is a need to actually modify data.
+
+There are multiple ways to enable/disable this feature. A config option
+CONFIG_OVERLAY_FS_METACOPY can be set/unset to enable/disable this feature
+by default. Or one can enable/disable it at module load time with module
+parameter metacopy=on/off. Lastly, there is also a per mount option
+metacopy=on/off to enable/disable this feature per mount.
+
+Do not use metacopy=on with untrusted upper/lower directories. Otherwise
+it is possible that an attacker can create a handcrafted file with
+appropriate REDIRECT and METACOPY xattrs, and gain access to file on lower
+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
+results in an error.
+
+[*] redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
+given.
+
+Sharing and copying layers
+--------------------------
+
+Lower layers may be shared among several overlay mounts and that is indeed
+a very common practice.  An overlay mount may use the same lower layer
+path as another overlay mount and it may use a lower layer path that is
+beneath or above the path of another overlay lower layer path.
+
+Using an upper layer path and/or a workdir path that are already used by
+another overlay mount is not allowed and may fail with EBUSY.  Using
+partially overlapping paths is not allowed and may fail with EBUSY.
+If files are accessed from two overlayfs mounts which share or overlap the
+upper layer and/or workdir path the behavior of the overlay is undefined,
+though it will not result in a crash or deadlock.
+
+Mounting an overlay using an upper layer path, where the upper layer path
+was previously used by another mounted overlay in combination with a
+different lower layer path, is allowed, unless the "inodes index" feature
+or "metadata only copy up" feature is enabled.
+
+With the "inodes index" feature, on the first time mount, an NFS file
+handle of the lower layer root directory, along with the UUID of the lower
+filesystem, are encoded and stored in the "trusted.overlay.origin" extended
+attribute on the upper layer root directory.  On subsequent mount attempts,
+the lower root directory file handle and lower filesystem UUID are compared
+to the stored origin in upper root directory.  On failure to verify the
+lower root origin, mount will fail with ESTALE.  An overlayfs mount with
+"inodes index" enabled will fail with EOPNOTSUPP if the lower filesystem
+does not support NFS export, lower filesystem does not have a valid UUID or
+if the upper filesystem does not support extended attributes.
+
+For "metadata only copy up" feature there is no verification mechanism at
+mount time. So if same upper is mounted with different set of lower, mount
+probably will succeed but expect the unexpected later on. So don't do it.
+
+It is quite a common practice to copy overlay layers to a different
+directory tree on the same or different underlying filesystem, and even
+to a different machine.  With the "inodes index" feature, trying to mount
+the copied layers will fail the verification of the lower root file handle.
+
+
+Non-standard behavior
+---------------------
+
+Current version of overlayfs can act as a mostly POSIX compliant
+filesystem.
+
+This is the list of cases that overlayfs doesn't currently handle:
+
+a) POSIX mandates updating st_atime for reads.  This is currently not
+done in the case when the file resides on a lower layer.
+
+b) If a file residing on a lower layer is opened for read-only and then
+memory mapped with MAP_SHARED, then subsequent changes to the file are not
+reflected in the memory mapping.
+
+The following options allow overlayfs to act more like a standards
+compliant filesystem:
+
+1) "redirect_dir"
+
+Enabled with the mount option or module option: "redirect_dir=on" or with
+the kernel config option CONFIG_OVERLAY_FS_REDIRECT_DIR=y.
+
+If this feature is disabled, then rename(2) on a lower or merged directory
+will fail with EXDEV ("Invalid cross-device link").
+
+2) "inode index"
+
+Enabled with the mount option or module option "index=on" or with the
+kernel config option CONFIG_OVERLAY_FS_INDEX=y.
+
+If this feature is disabled and a file with multiple hard links is copied
+up, then this will "break" the link.  Changes will not be propagated to
+other names referring to the same inode.
+
+3) "xino"
+
+Enabled with the mount option "xino=auto" or "xino=on", with the module
+option "xino_auto=on" or with the kernel config option
+CONFIG_OVERLAY_FS_XINO_AUTO=y.  Also implicitly enabled by using the same
+underlying filesystem for all layers making up the overlay.
+
+If this feature is disabled or the underlying filesystem doesn't have
+enough free bits in the inode number, then overlayfs will not be able to
+guarantee that the values of st_ino and st_dev returned by stat(2) and the
+value of d_ino returned by readdir(3) will act like on a normal filesystem.
+E.g. the value of st_dev may be different for two objects in the same
+overlay filesystem and the value of st_ino for directory objects may not be
+persistent and could change even while the overlay filesystem is mounted.
+
+
+Changes to underlying filesystems
+---------------------------------
+
+Offline changes, when the overlay is not mounted, are allowed to either
+the upper or the lower trees.
+
+Changes to the underlying filesystems while part of a mounted overlay
+filesystem are not allowed.  If the underlying filesystem is changed,
+the behavior of the overlay is undefined, though it will not result in
+a crash or deadlock.
+
+When the overlay NFS export feature is enabled, overlay filesystems
+behavior on offline changes of the underlying lower layer is different
+than the behavior when NFS export is disabled.
+
+On every copy_up, an NFS file handle of the lower inode, along with the
+UUID of the lower filesystem, are encoded and stored in an extended
+attribute "trusted.overlay.origin" on the upper inode.
+
+When the NFS export feature is enabled, a lookup of a merged directory,
+that found a lower directory at the lookup path or at the path pointed
+to by the "trusted.overlay.redirect" extended attribute, will verify
+that the found lower directory file handle and lower filesystem UUID
+match the origin file handle that was stored at copy_up time.  If a
+found lower directory does not match the stored origin, that directory
+will not be merged with the upper directory.
+
+
+
+NFS export
+----------
+
+When the underlying filesystems supports NFS export and the "nfs_export"
+feature is enabled, an overlay filesystem may be exported to NFS.
+
+With the "nfs_export" feature, on copy_up of any lower object, an index
+entry is created under the index directory.  The index entry name is the
+hexadecimal representation of the copy up origin file handle.  For a
+non-directory object, the index entry is a hard link to the upper inode.
+For a directory object, the index entry has an extended attribute
+"trusted.overlay.upper" with an encoded file handle of the upper
+directory inode.
+
+When encoding a file handle from an overlay filesystem object, the
+following rules apply:
+
+1. For a non-upper object, encode a lower file handle from lower inode
+2. For an indexed object, encode a lower file handle from copy_up origin
+3. For a pure-upper object and for an existing non-indexed upper object,
+   encode an upper file handle from upper inode
+
+The encoded overlay file handle includes:
+ - Header including path type information (e.g. lower/upper)
+ - UUID of the underlying filesystem
+ - Underlying filesystem encoding of underlying inode
+
+This encoding format is identical to the encoding format file handles that
+are stored in extended attribute "trusted.overlay.origin".
+
+When decoding an overlay file handle, the following steps are followed:
+
+1. Find underlying layer by UUID and path type information.
+2. Decode the underlying filesystem file handle to underlying dentry.
+3. For a lower file handle, lookup the handle in index directory by name.
+4. If a whiteout is found in index, return ESTALE. This represents an
+   overlay object that was deleted after its file handle was encoded.
+5. For a non-directory, instantiate a disconnected overlay dentry from the
+   decoded underlying dentry, the path type and index inode, if found.
+6. For a directory, use the connected underlying decoded dentry, path type
+   and index, to lookup a connected overlay dentry.
+
+Decoding a non-directory file handle may return a disconnected dentry.
+copy_up of that disconnected dentry will create an upper index entry with
+no upper alias.
+
+When overlay filesystem has multiple lower layers, a middle layer
+directory may have a "redirect" to lower directory.  Because middle layer
+"redirects" are not indexed, a lower file handle that was encoded from the
+"redirect" origin directory, cannot be used to find the middle or upper
+layer directory.  Similarly, a lower file handle that was encoded from a
+descendant of the "redirect" origin directory, cannot be used to
+reconstruct a connected overlay path.  To mitigate the cases of
+directories that cannot be decoded from a lower file handle, these
+directories are copied up on encode and encoded as an upper file handle.
+On an overlay filesystem with no upper layer this mitigation cannot be
+used NFS export in this setup requires turning off redirect follow (e.g.
+"redirect_dir=nofollow").
+
+The overlay filesystem does not support non-directory connectable file
+handles, so exporting with the 'subtree_check' exportfs configuration will
+cause failures to lookup files over NFS.
+
+When the NFS export feature is enabled, all directory index entries are
+verified on mount time to check that upper file handles are not stale.
+This verification may cause significant overhead in some cases.
+
+
+Testsuite
+---------
+
+There's a testsuite originally developed by David Howells and currently
+maintained by Amir Goldstein at:
+
+  https://github.com/amir73il/unionmount-testsuite.git
+
+Run as root:
+
+  # cd unionmount-testsuite
+  # ./run --ov --verify
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt
deleted file mode 100644 (file)
index 845d689..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-Written by: Neil Brown
-Please see MAINTAINERS file for where to send questions.
-
-Overlay Filesystem
-==================
-
-This document describes a prototype for a new approach to providing
-overlay-filesystem functionality in Linux (sometimes referred to as
-union-filesystems).  An overlay-filesystem tries to present a
-filesystem which is the result over overlaying one filesystem on top
-of the other.
-
-
-Overlay objects
----------------
-
-The overlay filesystem approach is 'hybrid', because the objects that
-appear in the filesystem do not always appear to belong to that filesystem.
-In many cases, an object accessed in the union will be indistinguishable
-from accessing the corresponding object from the original filesystem.
-This is most obvious from the 'st_dev' field returned by stat(2).
-
-While directories will report an st_dev from the overlay-filesystem,
-non-directory objects may report an st_dev from the lower filesystem or
-upper filesystem that is providing the object.  Similarly st_ino will
-only be unique when combined with st_dev, and both of these can change
-over the lifetime of a non-directory object.  Many applications and
-tools ignore these values and will not be affected.
-
-In the special case of all overlay layers on the same underlying
-filesystem, all objects will report an st_dev from the overlay
-filesystem and st_ino from the underlying filesystem.  This will
-make the overlay mount more compliant with filesystem scanners and
-overlay objects will be distinguishable from the corresponding
-objects in the original filesystem.
-
-On 64bit systems, even if all overlay layers are not on the same
-underlying filesystem, the same compliant behavior could be achieved
-with the "xino" feature.  The "xino" feature composes a unique object
-identifier from the real object st_ino and an underlying fsid index.
-If all underlying filesystems support NFS file handles and export file
-handles with 32bit inode number encoding (e.g. ext4), overlay filesystem
-will use the high inode number bits for fsid.  Even when the underlying
-filesystem uses 64bit inode numbers, users can still enable the "xino"
-feature with the "-o xino=on" overlay mount option.  That is useful for the
-case of underlying filesystems like xfs and tmpfs, which use 64bit inode
-numbers, but are very unlikely to use the high inode number bit.
-
-
-Upper and Lower
----------------
-
-An overlay filesystem combines two filesystems - an 'upper' filesystem
-and a 'lower' filesystem.  When a name exists in both filesystems, the
-object in the 'upper' filesystem is visible while the object in the
-'lower' filesystem is either hidden or, in the case of directories,
-merged with the 'upper' object.
-
-It would be more correct to refer to an upper and lower 'directory
-tree' rather than 'filesystem' as it is quite possible for both
-directory trees to be in the same filesystem and there is no
-requirement that the root of a filesystem be given for either upper or
-lower.
-
-The lower filesystem can be any filesystem supported by Linux and does
-not need to be writable.  The lower filesystem can even be another
-overlayfs.  The upper filesystem will normally be writable and if it
-is it must support the creation of trusted.* extended attributes, and
-must provide valid d_type in readdir responses, so NFS is not suitable.
-
-A read-only overlay of two read-only filesystems may use any
-filesystem type.
-
-Directories
------------
-
-Overlaying mainly involves directories.  If a given name appears in both
-upper and lower filesystems and refers to a non-directory in either,
-then the lower object is hidden - the name refers only to the upper
-object.
-
-Where both upper and lower objects are directories, a merged directory
-is formed.
-
-At mount time, the two directories given as mount options "lowerdir" and
-"upperdir" are combined into a merged directory:
-
-  mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
-  workdir=/work /merged
-
-The "workdir" needs to be an empty directory on the same filesystem
-as upperdir.
-
-Then whenever a lookup is requested in such a merged directory, the
-lookup is performed in each actual directory and the combined result
-is cached in the dentry belonging to the overlay filesystem.  If both
-actual lookups find directories, both are stored and a merged
-directory is created, otherwise only one is stored: the upper if it
-exists, else the lower.
-
-Only the lists of names from directories are merged.  Other content
-such as metadata and extended attributes are reported for the upper
-directory only.  These attributes of the lower directory are hidden.
-
-whiteouts and opaque directories
---------------------------------
-
-In order to support rm and rmdir without changing the lower
-filesystem, an overlay filesystem needs to record in the upper filesystem
-that files have been removed.  This is done using whiteouts and opaque
-directories (non-directories are always opaque).
-
-A whiteout is created as a character device with 0/0 device number.
-When a whiteout is found in the upper level of a merged directory, any
-matching name in the lower level is ignored, and the whiteout itself
-is also hidden.
-
-A directory is made opaque by setting the xattr "trusted.overlay.opaque"
-to "y".  Where the upper filesystem contains an opaque directory, any
-directory in the lower filesystem with the same name is ignored.
-
-readdir
--------
-
-When a 'readdir' request is made on a merged directory, the upper and
-lower directories are each read and the name lists merged in the
-obvious way (upper is read first, then lower - entries that already
-exist are not re-added).  This merged name list is cached in the
-'struct file' and so remains as long as the file is kept open.  If the
-directory is opened and read by two processes at the same time, they
-will each have separate caches.  A seekdir to the start of the
-directory (offset 0) followed by a readdir will cause the cache to be
-discarded and rebuilt.
-
-This means that changes to the merged directory do not appear while a
-directory is being read.  This is unlikely to be noticed by many
-programs.
-
-seek offsets are assigned sequentially when the directories are read.
-Thus if
-
-  - read part of a directory
-  - remember an offset, and close the directory
-  - re-open the directory some time later
-  - seek to the remembered offset
-
-there may be little correlation between the old and new locations in
-the list of filenames, particularly if anything has changed in the
-directory.
-
-Readdir on directories that are not merged is simply handled by the
-underlying directory (upper or lower).
-
-renaming directories
---------------------
-
-When renaming a directory that is on the lower layer or merged (i.e. the
-directory was not created on the upper layer to start with) overlayfs can
-handle it in two different ways:
-
-1. return EXDEV error: this error is returned by rename(2) when trying to
-   move a file or directory across filesystem boundaries.  Hence
-   applications are usually prepared to hande this error (mv(1) for example
-   recursively copies the directory tree).  This is the default behavior.
-
-2. If the "redirect_dir" feature is enabled, then the directory will be
-   copied up (but not the contents).  Then the "trusted.overlay.redirect"
-   extended attribute is set to the path of the original location from the
-   root of the overlay.  Finally the directory is moved to the new
-   location.
-
-There are several ways to tune the "redirect_dir" feature.
-
-Kernel config options:
-
-- OVERLAY_FS_REDIRECT_DIR:
-    If this is enabled, then redirect_dir is turned on by  default.
-- OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW:
-    If this is enabled, then redirects are always followed by default. Enabling
-    this results in a less secure configuration.  Enable this option only when
-    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/*):
-
-- "redirect_dir=BOOL":
-    See OVERLAY_FS_REDIRECT_DIR kernel config option above.
-- "redirect_always_follow=BOOL":
-    See OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW kernel config option above.
-- "redirect_max=NUM":
-    The maximum number of bytes in an absolute redirect (default is 256).
-
-Mount options:
-
-- "redirect_dir=on":
-    Redirects are enabled.
-- "redirect_dir=follow":
-    Redirects are not created, but followed.
-- "redirect_dir=off":
-    Redirects are not created and only followed if "redirect_always_follow"
-    feature is enabled in the kernel/module config.
-- "redirect_dir=nofollow":
-    Redirects are not created and not followed (equivalent to "redirect_dir=off"
-    if "redirect_always_follow" feature is not enabled).
-
-When the NFS export feature is enabled, every copied up directory is
-indexed by the file handle of the lower inode and a file handle of the
-upper directory is stored in a "trusted.overlay.upper" extended attribute
-on the index entry.  On lookup of a merged directory, if the upper
-directory does not match the file handle stores in the index, that is an
-indication that multiple upper directories may be redirected to the same
-lower directory.  In that case, lookup returns an error and warns about
-a possible inconsistency.
-
-Because lower layer redirects cannot be verified with the index, enabling
-NFS export support on an overlay filesystem with no upper layer requires
-turning off redirect follow (e.g. "redirect_dir=nofollow").
-
-
-Non-directories
----------------
-
-Objects that are not directories (files, symlinks, device-special
-files etc.) are presented either from the upper or lower filesystem as
-appropriate.  When a file in the lower filesystem is accessed in a way
-the requires write-access, such as opening for write access, changing
-some metadata etc., the file is first copied from the lower filesystem
-to the upper filesystem (copy_up).  Note that creating a hard-link
-also requires copy_up, though of course creation of a symlink does
-not.
-
-The copy_up may turn out to be unnecessary, for example if the file is
-opened for read-write but the data is not modified.
-
-The copy_up process first makes sure that the containing directory
-exists in the upper filesystem - creating it and any parents as
-necessary.  It then creates the object with the same metadata (owner,
-mode, mtime, symlink-target etc.) and then if the object is a file, the
-data is copied from the lower to the upper filesystem.  Finally any
-extended attributes are copied up.
-
-Once the copy_up is complete, the overlay filesystem simply
-provides direct access to the newly created file in the upper
-filesystem - future operations on the file are barely noticed by the
-overlay filesystem (though an operation on the name of the file such as
-rename or unlink will of course be noticed and handled).
-
-
-Multiple lower layers
----------------------
-
-Multiple lower layers can now be given using the the colon (":") as a
-separator character between the directory names.  For example:
-
-  mount -t overlay overlay -olowerdir=/lower1:/lower2:/lower3 /merged
-
-As the example shows, "upperdir=" and "workdir=" may be omitted.  In
-that case the overlay will be read-only.
-
-The specified lower directories will be stacked beginning from the
-rightmost one and going left.  In the above example lower1 will be the
-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
-like chown/chmod is performed. Full file will be copied up later when
-file is opened for WRITE operation.
-
-In other words, this is delayed data copy up operation and data is copied
-up when there is a need to actually modify data.
-
-There are multiple ways to enable/disable this feature. A config option
-CONFIG_OVERLAY_FS_METACOPY can be set/unset to enable/disable this feature
-by default. Or one can enable/disable it at module load time with module
-parameter metacopy=on/off. Lastly, there is also a per mount option
-metacopy=on/off to enable/disable this feature per mount.
-
-Do not use metacopy=on with untrusted upper/lower directories. Otherwise
-it is possible that an attacker can create a handcrafted file with
-appropriate REDIRECT and METACOPY xattrs, and gain access to file on lower
-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
-results in an error.
-
-(*) redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
-given.
-
-Sharing and copying layers
---------------------------
-
-Lower layers may be shared among several overlay mounts and that is indeed
-a very common practice.  An overlay mount may use the same lower layer
-path as another overlay mount and it may use a lower layer path that is
-beneath or above the path of another overlay lower layer path.
-
-Using an upper layer path and/or a workdir path that are already used by
-another overlay mount is not allowed and may fail with EBUSY.  Using
-partially overlapping paths is not allowed and may fail with EBUSY.
-If files are accessed from two overlayfs mounts which share or overlap the
-upper layer and/or workdir path the behavior of the overlay is undefined,
-though it will not result in a crash or deadlock.
-
-Mounting an overlay using an upper layer path, where the upper layer path
-was previously used by another mounted overlay in combination with a
-different lower layer path, is allowed, unless the "inodes index" feature
-or "metadata only copy up" feature is enabled.
-
-With the "inodes index" feature, on the first time mount, an NFS file
-handle of the lower layer root directory, along with the UUID of the lower
-filesystem, are encoded and stored in the "trusted.overlay.origin" extended
-attribute on the upper layer root directory.  On subsequent mount attempts,
-the lower root directory file handle and lower filesystem UUID are compared
-to the stored origin in upper root directory.  On failure to verify the
-lower root origin, mount will fail with ESTALE.  An overlayfs mount with
-"inodes index" enabled will fail with EOPNOTSUPP if the lower filesystem
-does not support NFS export, lower filesystem does not have a valid UUID or
-if the upper filesystem does not support extended attributes.
-
-For "metadata only copy up" feature there is no verification mechanism at
-mount time. So if same upper is mounted with different set of lower, mount
-probably will succeed but expect the unexpected later on. So don't do it.
-
-It is quite a common practice to copy overlay layers to a different
-directory tree on the same or different underlying filesystem, and even
-to a different machine.  With the "inodes index" feature, trying to mount
-the copied layers will fail the verification of the lower root file handle.
-
-
-Non-standard behavior
----------------------
-
-Current version of overlayfs can act as a mostly POSIX compliant
-filesystem.
-
-This is the list of cases that overlayfs doesn't currently handle:
-
-a) POSIX mandates updating st_atime for reads.  This is currently not
-done in the case when the file resides on a lower layer.
-
-b) If a file residing on a lower layer is opened for read-only and then
-memory mapped with MAP_SHARED, then subsequent changes to the file are not
-reflected in the memory mapping.
-
-The following options allow overlayfs to act more like a standards
-compliant filesystem:
-
-1) "redirect_dir"
-
-Enabled with the mount option or module option: "redirect_dir=on" or with
-the kernel config option CONFIG_OVERLAY_FS_REDIRECT_DIR=y.
-
-If this feature is disabled, then rename(2) on a lower or merged directory
-will fail with EXDEV ("Invalid cross-device link").
-
-2) "inode index"
-
-Enabled with the mount option or module option "index=on" or with the
-kernel config option CONFIG_OVERLAY_FS_INDEX=y.
-
-If this feature is disabled and a file with multiple hard links is copied
-up, then this will "break" the link.  Changes will not be propagated to
-other names referring to the same inode.
-
-3) "xino"
-
-Enabled with the mount option "xino=auto" or "xino=on", with the module
-option "xino_auto=on" or with the kernel config option
-CONFIG_OVERLAY_FS_XINO_AUTO=y.  Also implicitly enabled by using the same
-underlying filesystem for all layers making up the overlay.
-
-If this feature is disabled or the underlying filesystem doesn't have
-enough free bits in the inode number, then overlayfs will not be able to
-guarantee that the values of st_ino and st_dev returned by stat(2) and the
-value of d_ino returned by readdir(3) will act like on a normal filesystem.
-E.g. the value of st_dev may be different for two objects in the same
-overlay filesystem and the value of st_ino for directory objects may not be
-persistent and could change even while the overlay filesystem is mounted.
-
-
-Changes to underlying filesystems
----------------------------------
-
-Offline changes, when the overlay is not mounted, are allowed to either
-the upper or the lower trees.
-
-Changes to the underlying filesystems while part of a mounted overlay
-filesystem are not allowed.  If the underlying filesystem is changed,
-the behavior of the overlay is undefined, though it will not result in
-a crash or deadlock.
-
-When the overlay NFS export feature is enabled, overlay filesystems
-behavior on offline changes of the underlying lower layer is different
-than the behavior when NFS export is disabled.
-
-On every copy_up, an NFS file handle of the lower inode, along with the
-UUID of the lower filesystem, are encoded and stored in an extended
-attribute "trusted.overlay.origin" on the upper inode.
-
-When the NFS export feature is enabled, a lookup of a merged directory,
-that found a lower directory at the lookup path or at the path pointed
-to by the "trusted.overlay.redirect" extended attribute, will verify
-that the found lower directory file handle and lower filesystem UUID
-match the origin file handle that was stored at copy_up time.  If a
-found lower directory does not match the stored origin, that directory
-will not be merged with the upper directory.
-
-
-
-NFS export
-----------
-
-When the underlying filesystems supports NFS export and the "nfs_export"
-feature is enabled, an overlay filesystem may be exported to NFS.
-
-With the "nfs_export" feature, on copy_up of any lower object, an index
-entry is created under the index directory.  The index entry name is the
-hexadecimal representation of the copy up origin file handle.  For a
-non-directory object, the index entry is a hard link to the upper inode.
-For a directory object, the index entry has an extended attribute
-"trusted.overlay.upper" with an encoded file handle of the upper
-directory inode.
-
-When encoding a file handle from an overlay filesystem object, the
-following rules apply:
-
-1. For a non-upper object, encode a lower file handle from lower inode
-2. For an indexed object, encode a lower file handle from copy_up origin
-3. For a pure-upper object and for an existing non-indexed upper object,
-   encode an upper file handle from upper inode
-
-The encoded overlay file handle includes:
- - Header including path type information (e.g. lower/upper)
- - UUID of the underlying filesystem
- - Underlying filesystem encoding of underlying inode
-
-This encoding format is identical to the encoding format file handles that
-are stored in extended attribute "trusted.overlay.origin".
-
-When decoding an overlay file handle, the following steps are followed:
-
-1. Find underlying layer by UUID and path type information.
-2. Decode the underlying filesystem file handle to underlying dentry.
-3. For a lower file handle, lookup the handle in index directory by name.
-4. If a whiteout is found in index, return ESTALE. This represents an
-   overlay object that was deleted after its file handle was encoded.
-5. For a non-directory, instantiate a disconnected overlay dentry from the
-   decoded underlying dentry, the path type and index inode, if found.
-6. For a directory, use the connected underlying decoded dentry, path type
-   and index, to lookup a connected overlay dentry.
-
-Decoding a non-directory file handle may return a disconnected dentry.
-copy_up of that disconnected dentry will create an upper index entry with
-no upper alias.
-
-When overlay filesystem has multiple lower layers, a middle layer
-directory may have a "redirect" to lower directory.  Because middle layer
-"redirects" are not indexed, a lower file handle that was encoded from the
-"redirect" origin directory, cannot be used to find the middle or upper
-layer directory.  Similarly, a lower file handle that was encoded from a
-descendant of the "redirect" origin directory, cannot be used to
-reconstruct a connected overlay path.  To mitigate the cases of
-directories that cannot be decoded from a lower file handle, these
-directories are copied up on encode and encoded as an upper file handle.
-On an overlay filesystem with no upper layer this mitigation cannot be
-used NFS export in this setup requires turning off redirect follow (e.g.
-"redirect_dir=nofollow").
-
-The overlay filesystem does not support non-directory connectable file
-handles, so exporting with the 'subtree_check' exportfs configuration will
-cause failures to lookup files over NFS.
-
-When the NFS export feature is enabled, all directory index entries are
-verified on mount time to check that upper file handles are not stale.
-This verification may cause significant overhead in some cases.
-
-
-Testsuite
----------
-
-There's a testsuite originally developed by David Howells and currently
-maintained by Amir Goldstein at:
-
-  https://github.com/amir73il/unionmount-testsuite.git
-
-Run as root:
-
-  # cd unionmount-testsuite
-  # ./run --ov --verify
index 74bef19f69f0a8078f2f988358ff57046b46210b..231e6a64957fcf12915c41b6a8d48d6978fa2690 100644 (file)
@@ -196,14 +196,11 @@ applicable everywhere (see syntax).
   or equal to the first symbol and smaller than or equal to the second
   symbol.
 
-- help text: "help" or "---help---"
+- help text: "help"
 
   This defines a help text. The end of the help text is determined by
   the indentation level, this means it ends at the first line which has
   a smaller indentation than the first line of the help text.
-  "---help---" and "help" do not differ in behaviour, "---help---" is
-  used to help visually separate configuration logic from help within
-  the file as an aid to developers.
 
 - misc options: "option" <symbol>[=<value>]
 
index b9b50553bfc56b5b5b50ea9513700a4421f7e232..d7e6534a8505eeb4f9dcc24b01ef94d674e8bf3e 100644 (file)
@@ -297,9 +297,19 @@ more details, with real examples.
        If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular)
        the corresponding obj- variable will be set, and kbuild will descend
        down in the ext2 directory.
-       Kbuild only uses this information to decide that it needs to visit
-       the directory, it is the Makefile in the subdirectory that
-       specifies what is modular and what is built-in.
+
+       Kbuild uses this information not only to decide that it needs to visit
+       the directory, but also to decide whether or not to link objects from
+       the directory into vmlinux.
+
+       When Kbuild descends into the directory with 'y', all built-in objects
+       from that directory are combined into the built-in.a, which will be
+       eventually linked into vmlinux.
+
+       When Kbuild descends into the directory with 'm', in contrast, nothing
+       from that directory will be linked into vmlinux. If the Makefile in
+       that directory specifies obj-y, those objects will be left orphan.
+       It is very likely a bug of the Makefile or of dependencies in Kconfig.
 
        It is good practice to use a `CONFIG_` variable when assigning directory
        names. This allows kbuild to totally skip the directory if the
index ada573b7d703bca0b0ab725e2714f84f6dd2bd1f..edb296c52f61e4b6c1b7b67a30302260ffcb015c 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 201f80c7c0506e5e5772006b9f874d4081920d6f..df129f55ace5e768740312b0b60b903b76872ab6 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 8995d2d19f202e65d37d960705991c314a5bfcaa..8725f2b9e96032d37ac6a3c379ce254fd652e5d8 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 4f6237392e65ad33b393a337d4d898314c600290..eae10bc7f86f2a096f970e6464087c7f31b9aea8 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 e34488f7baae110588f492d6b246d321ef97717a..06db726b6a943b8485751b2e146f659e556a5204 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
@@ -12394,7 +12396,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>
@@ -16324,12 +16326,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 73e3c280292770ccd4b5bb1be95c2fca391bfba8..e51b53c180bc0b051808a381cff8757af0951c72 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -414,6 +414,7 @@ STRIP               = $(CROSS_COMPILE)strip
 OBJCOPY                = $(CROSS_COMPILE)objcopy
 OBJDUMP                = $(CROSS_COMPILE)objdump
 OBJSIZE                = $(CROSS_COMPILE)size
+READELF                = $(CROSS_COMPILE)readelf
 PAHOLE         = pahole
 LEX            = flex
 YACC           = bison
@@ -472,7 +473,7 @@ GCC_PLUGINS_CFLAGS :=
 CLANG_FLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
 export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
 export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
index dc05a63516f5b5a3c695578cd864b2f3886910ba..27ea64b1fa3321c3d86f2c25b419e1fd1882b269 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 8678e6e35493fc7b6548942ed643feec16a51407..e5fdb7abb0d54a47eceb026009d1ef1173de7e7f 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
 };
 
 &i2c0 {
index cae4500194fecb5e9a7d5c370300fea5ff550148..811c8cae315b520f445964fc07dc00e16266b5f9 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 95314121d11153ba8b9330728bab031f40585fda..078cb473fa7dcd08f27f6a1e094c6855e825fb26 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 2dac3efc7640595c352037485ebd89bfde7cff76..1bc45cfd545385c640fdf2c17b6c9da2e08af2c8 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 961bed832755b0389b93053c7cbf2e5b4dadacbc..e2f6ffb00aa94340fc2db94fb7e75b0e7d998bca 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 3caaa57eb6c81eb449b6ee8dbdc04101b5b32d00..839491628e87b392cce339a83b8ec261ab70cbf3 100644 (file)
@@ -37,7 +37,7 @@
 
                        trips {
                                cpu-crit {
-                                       temperature     = <80000>;
+                                       temperature     = <90000>;
                                        hysteresis      = <0>;
                                        type            = "critical";
                                };
index 372dc1eb88a0e82883e2049cec701034f8374b2d..2d9b4dd058307e7f1c5c44bae5e4f2e75d5ea6c3 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 6472b056a001f9054c525635ab48611bb114240b..5a2c5320437dd246835d8a217c8cfad65694b1d0 100644 (file)
                                regulator-name = "LDORTC1";
                                regulator-boot-on;
                        };
-
-                       ldortc2_reg: LDORTC2 {
-                               regulator-name = "LDORTC2";
-                               regulator-boot-on;
-                       };
                };
        };
 };
index 1506eb12b21e08a8ba316e38ac667690f19a19f2..212144511b661b28cbb8b6f34aeac7261eeec316 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 e7e4bb5ad8d5c3d73295ad724f9a7a6e8e74a217..fde84f123fbb5502ab07952e09e46c4e7c9b9cb2 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 26d6dee67aa6de729fdb20921b795649d9f04219..3608e55eaecdf46aa52fec6ff02134773d07fad5 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 8c37cc8ab6f2bb938f7fca8bd239054c286883ec..c32c338f770426bcb6c97e7a36ca2bd34b241b00 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 bda57cafa2bcb9cc5ec572e35cf083195bbbded8..de3830443613e94956c9d463fcff15780702b145 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 f3f42cf3b8937e3e28fd01a6e2ab4890335f0dd3..776ae07e04697527754a463647e34ed882faa1ee 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 dbe296798647fd92030a0ad2c5e57e14e2d0aa22..fa0300d8c79daae2da19e3290976994bc6536e1e 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 d8118031c51f710a668cbb7f66e4cb4025d4d38e..871f98342d50e67e9962ae863436bf839c8cb4e7 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 0331c58b07a26a9c8415496c8da068f8b899d43a..dff651b9f252d4451dce883ec5fcd06d2129fda3 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 354e0e7025aec5c1da2145ae4037f7e805868970..1da11bdb1dfbd6f1ce906b83ba2d84ecd396f316 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 8e8a77eb596ae47afca5c62f1842b3a68c02d433..13a3cbe89b5a65deaf03202928d0209fb77dcb46 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 6a09ca7644ea16faa70073625d05f19da0605bdd..85f4bec22f6d4ead1f60b0a1b380ce479867e207 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 ba8f82a29a816a0bc7b5a6793403ccfa09f5c7d9..e794b2d53adfcf9d9c0a94d93f7e3109c725ae40 100644 (file)
@@ -44,13 +44,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
@@ -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 b56af759dcdfcc2b8c3d19ff7bfed99bda0ddde2..819bdfcc2e714d64ba1657de319dcc1ba6b6a5da 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 f627c37dad9c92a7beeb277ead459726afcf5dad..ab5c215cf46c3d81a5ef840fe46ffe740174c7ec 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 a99ea747d7edefb681d7eca88917efaca7c245aa..87e17400699551f07af20cf152392bf76c26d9df 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 2663c8f8be115a0929b2e6f933f4b3e05ca9e98d..068d90950d9378e0a50e13d531c6c16cd85751d7 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 3b330e58a4f033e19ca59a711a0c8e3ddd6842c1..a6c9f49c661287cde50d42c09a3c67bf1f9ddb31 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 36434d4da381a2691fea6918b2eda3203bc44dc9..749c4579db0d5542ac274a8198f9f3d825be4d3b 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 e9a960e28f3c8468af557533ce3f9b71154d7cac..1b55fc08f8532c38b32c0349c5051e40e59be757 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 15002b51ff18df83d5d5a5c37c2c65462fffcdc3..c92fe7fe9692ceedcb98d2a88afdecea689bbaca 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 5645bc9cbc09a28c1fbc324743e4d568c3033dc6..add67498c126bffdc8050f804bed16fa97efd8e4 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 0496e66aaa565fbe69f8fb238f503b0eccb6a27f..c6fbbd29bd8717a44bcac3cc5706269867d9d272 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 f69a6aab7bfbb5cb65fd082eaedb939d46c12149..1ddb26394e8ac5a1739b6f5aaf12512e5c3ed9f6 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 507b18b1660e6e2221242b24d9b8e90055d42842..169872bc08928aa5fc566355ac0e5165985a1d00 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 9488b63dfc872d2bb7fc3350e1adf22251581f58..617c2777926fc15344937701d9d02f2bbc09c962 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 090af2d2d3e4c512f4e04356d01bfe968869cc35..96eb8e43f39b5484db1f22192ff20740276b7a2b 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 6e5a2a4faeab0d9fe4b49851ecee60d6e7baada4..4ec2a9f14f845cebe96449faeb32914abcf55eae 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 d57b46e0dd6044d1a918e8a518f4fead29ad5c0e..0acc9d5fb19e9a638c8bdc4f6f699d5b62689e7d 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 91571841df8a70d0ea2520dd9c3977e6f85ccc24..9dba7e88088530726862179d53ebc5f8ff986ce6 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 0a40201f315ffd14dd39c9a7b71274c1d3db25a3..0c8421dd01ab5bc911e24f340dbe80407089c204 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 634759ac8c717a8d0c2b5774ceb9ec9ce53da86b..d325b67d00dfcf70c4f3cf89e68e3964eec62a06 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 a474f98ce4fae8d49e65dec1f8da26d72c70745b..36db8145f9f46013c2b1b31e3c7e9f75e4dce349 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 d4051e88e6250ddbb621b18c0dc6f8356411ffd8..bc88841d335d20816596d354060341d2377c4df8 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 6dc6c4fbc8e2b1a59796afb96bff120d4c0f8a21..69289e99cabdcee175a4a176881a128f49e3a574 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 6da8885251d65d9499fbf5b3cc4491f9ee1170cd..670f14a228e55bb42c4cc516b660f91431a4cb0a 100644 (file)
@@ -194,9 +194,9 @@ static inline unsigned long long get_tod_clock_monotonic(void)
 {
        unsigned long long tod;
 
-       preempt_disable();
+       preempt_disable_notrace();
        tod = get_tod_clock() - *(unsigned long long *) &tod_clock_base[1];
-       preempt_enable();
+       preempt_enable_notrace();
        return tod;
 }
 
index ef3c00b049ab45b4cd050d97a30e8210b63f7676..4093a2856929a0a420b82c819116fc6d4da6e90b 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 db32a55daaec605a7b0042f7c4eb126996c9ccba..cd241ee66eff4feb6d39842ac9972136394e23c1 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 9e1660a6b9db6e49be93e4b145bb639dee52d773..c3597d2e2ae0e2ff57f2d1d3b80f89152968da17 100644 (file)
@@ -35,6 +35,7 @@ EXPORT_SYMBOL(_mcount)
 ENTRY(ftrace_caller)
        .globl  ftrace_regs_caller
        .set    ftrace_regs_caller,ftrace_caller
+       stg     %r14,(__SF_GPRS+8*8)(%r15)      # save traced function caller
        lgr     %r1,%r15
 #if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
        aghi    %r0,MCOUNT_RETURN_FIXUP
index c07fdcd737266de36e821eae1d0fcc0bb41abf27..77d93c534284d0bba7b1a02f99e743d9d5ff8292 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 2794cad9312e37cda034425386edf7356f2e6d97..a08bd2522dd95a08a27de50850e60546fedb31e5 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 da2d4d4c5b0e0252186df8d985cf3dafa7fb6994..707fd99f6734d86ca1f037887f6be085b7366a3c 100644 (file)
@@ -36,10 +36,17 @@ static bool update_stack_info(struct unwind_state *state, unsigned long sp)
        return true;
 }
 
-static inline bool is_task_pt_regs(struct unwind_state *state,
-                                  struct pt_regs *regs)
+static inline bool is_final_pt_regs(struct unwind_state *state,
+                                   struct pt_regs *regs)
 {
-       return task_pt_regs(state->task) == regs;
+       /* user mode or kernel thread pt_regs at the bottom of task stack */
+       if (task_pt_regs(state->task) == regs)
+               return true;
+
+       /* user mode pt_regs at the bottom of irq stack */
+       return state->stack_info.type == STACK_TYPE_IRQ &&
+              state->stack_info.end - sizeof(struct pt_regs) == (unsigned long)regs &&
+              READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE;
 }
 
 bool unwind_next_frame(struct unwind_state *state)
@@ -80,7 +87,7 @@ bool unwind_next_frame(struct unwind_state *state)
                        if (!on_stack(info, sp, sizeof(struct pt_regs)))
                                goto out_err;
                        regs = (struct pt_regs *) sp;
-                       if (is_task_pt_regs(state, regs))
+                       if (is_final_pt_regs(state, regs))
                                goto out_stop;
                        ip = READ_ONCE_NOCHECK(regs->psw.addr);
                        sp = READ_ONCE_NOCHECK(regs->gprs[15]);
index ce1e4bbe53aaf2d447f4aa82a4ba1c55ffdc13e6..9b2dab5a69f995055c9067f37a5688d65f1b4642 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 bda7ac0ddd29710d62bb23911408cc4e64adc329..32b7a30b2485d53f9dede2756ddfb7ce105bc4da 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 460f2557294021f0f7bd49e1f31bcfbaed007f31..06345616a6466a921c9476ca6ecf6a0710a3638a 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 04a03433c72013b0bbf5a93bb72b477d0cd2d709..c82157f46b18693cf6ed6272934ed6cb5a205490 100644 (file)
@@ -1,3 +1,4 @@
 purgatory
+purgatory.chk
 purgatory.lds
 purgatory.ro
index bc0d7a0d039453d28464432c2d74994b827b4c1d..c57f8c40e992685812170f3db796256b7e620934 100644 (file)
@@ -4,7 +4,7 @@ OBJECT_FILES_NON_STANDARD := y
 
 purgatory-y := head.o purgatory.o string.o sha256.o mem.o
 
-targets += $(purgatory-y) purgatory.lds purgatory purgatory.ro
+targets += $(purgatory-y) purgatory.lds purgatory purgatory.chk purgatory.ro
 PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
 
 $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE
@@ -15,8 +15,10 @@ CFLAGS_sha256.o := -D__DISABLE_EXPORTS
 $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE
        $(call if_changed_rule,as_o_S)
 
-$(obj)/string.o: $(srctree)/arch/s390/lib/string.c FORCE
-       $(call if_changed_rule,cc_o_c)
+KCOV_INSTRUMENT := n
+GCOV_PROFILE := n
+UBSAN_SANITIZE := n
+KASAN_SANITIZE := n
 
 KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
 KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
@@ -26,15 +28,22 @@ KBUILD_CFLAGS += $(CLANG_FLAGS)
 KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
 KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
 
-LDFLAGS_purgatory := -r --no-undefined -nostdlib -z nodefaultlib -T
+# Since we link purgatory with -r unresolved symbols are not checked, so we
+# also link a purgatory.chk binary without -r to check for unresolved symbols.
+PURGATORY_LDFLAGS := -nostdlib -z nodefaultlib
+LDFLAGS_purgatory := -r $(PURGATORY_LDFLAGS) -T
+LDFLAGS_purgatory.chk := -e purgatory_start $(PURGATORY_LDFLAGS)
 $(obj)/purgatory: $(obj)/purgatory.lds $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
 
+$(obj)/purgatory.chk: $(obj)/purgatory FORCE
+               $(call if_changed,ld)
+
 OBJCOPYFLAGS_purgatory.ro := -O elf64-s390
 OBJCOPYFLAGS_purgatory.ro += --remove-section='*debug*'
 OBJCOPYFLAGS_purgatory.ro += --remove-section='.comment'
 OBJCOPYFLAGS_purgatory.ro += --remove-section='.note.*'
-$(obj)/purgatory.ro: $(obj)/purgatory FORCE
+$(obj)/purgatory.ro: $(obj)/purgatory $(obj)/purgatory.chk FORCE
                $(call if_changed,objcopy)
 
 $(obj)/kexec-purgatory.o: $(obj)/kexec-purgatory.S $(obj)/purgatory.ro FORCE
diff --git a/arch/s390/purgatory/string.c b/arch/s390/purgatory/string.c
new file mode 100644 (file)
index 0000000..c98c22a
--- /dev/null
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+#define __HAVE_ARCH_MEMCMP     /* arch function */
+#include "../lib/string.c"
index f6d148451dfc724eb8f2fa5bf4916d8d459136d8..f3dc3f25b3ff08c2af8bd2a1db845fd2c6308ded 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 6d61f8cf4c131dac3b48b33acc4635f85814a32e..0d5f3c9d52f30edbcbf51141b8de16a294236903 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 84cc8f7f83e9934e1aae5b4d38d3ce099c38e32a..c8eabb973b8688648dff42f70bd6f05b43a35103 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 aa976adb7094ee37158a901a3372b079df13bcb8..1dac210f7d446b906b3c75969331a46a84db2249 100644 (file)
@@ -103,7 +103,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 quiet_cmd_check_data_rel = DATAREL $@
 define cmd_check_data_rel
        for obj in $(filter %.o,$^); do \
-               ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
+               $(READELF) -S $$obj | grep -qF .rel.local && { \
                        echo "error: $$obj has data relocations!" >&2; \
                        exit 1; \
                } || true; \
index 9a89d98c55bd8e87a245024bb0fa635ab0f56dd3..f118af9f0718bec9b0456d7e47d2c78b6489cd02 100644 (file)
@@ -376,7 +376,7 @@ int x86_add_exclusive(unsigned int what)
         * LBR and BTS are still mutually exclusive.
         */
        if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
-               return 0;
+               goto out;
 
        if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
                mutex_lock(&pmc_reserve_mutex);
@@ -388,6 +388,7 @@ int x86_add_exclusive(unsigned int what)
                mutex_unlock(&pmc_reserve_mutex);
        }
 
+out:
        atomic_inc(&active_events);
        return 0;
 
@@ -398,11 +399,15 @@ fail_unlock:
 
 void x86_del_exclusive(unsigned int what)
 {
+       atomic_dec(&active_events);
+
+       /*
+        * See the comment in x86_add_exclusive().
+        */
        if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
                return;
 
        atomic_dec(&x86_pmu.lbr_exclusive[what]);
-       atomic_dec(&active_events);
 }
 
 int x86_setup_perfctr(struct perf_event *event)
@@ -1642,9 +1647,12 @@ static struct attribute_group x86_pmu_format_group __ro_after_init = {
 
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page)
 {
-       struct perf_pmu_events_attr *pmu_attr = \
+       struct perf_pmu_events_attr *pmu_attr =
                container_of(attr, struct perf_pmu_events_attr, attr);
-       u64 config = x86_pmu.event_map(pmu_attr->id);
+       u64 config = 0;
+
+       if (pmu_attr->id < x86_pmu.max_events)
+               config = x86_pmu.event_map(pmu_attr->id);
 
        /* string trumps id */
        if (pmu_attr->event_str)
@@ -1713,6 +1721,9 @@ is_visible(struct kobject *kobj, struct attribute *attr, int idx)
 {
        struct perf_pmu_events_attr *pmu_attr;
 
+       if (idx >= x86_pmu.max_events)
+               return 0;
+
        pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
        /* str trumps id */
        return pmu_attr->event_str || x86_pmu.event_map(idx) ? attr->mode : 0;
index 38de4a7f6752b23a58ed8e68934017def83969ed..6a3b599ee0fe7df0fe8010218100e8f9db08acf5 100644 (file)
@@ -63,9 +63,17 @@ struct bts_buffer {
 
 static struct pmu bts_pmu;
 
+static int buf_nr_pages(struct page *page)
+{
+       if (!PagePrivate(page))
+               return 1;
+
+       return 1 << page_private(page);
+}
+
 static size_t buf_size(struct page *page)
 {
-       return 1 << (PAGE_SHIFT + page_private(page));
+       return buf_nr_pages(page) * PAGE_SIZE;
 }
 
 static void *
@@ -83,9 +91,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
        /* count all the high order buffers */
        for (pg = 0, nbuf = 0; pg < nr_pages;) {
                page = virt_to_page(pages[pg]);
-               if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
-                       return NULL;
-               pg += 1 << page_private(page);
+               pg += buf_nr_pages(page);
                nbuf++;
        }
 
@@ -109,7 +115,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
                unsigned int __nr_pages;
 
                page = virt_to_page(pages[pg]);
-               __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+               __nr_pages = buf_nr_pages(page);
                buf->buf[nbuf].page = page;
                buf->buf[nbuf].offset = offset;
                buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
index 5167bd2bb6b14dae63313d1def4d93ed1eaac38d..d6cf5c18a7e04a3b09a07179ff1fce8a4790ec8f 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 5f42f25bac8f8c9643def8bae0b93d513c9fbb8b..2e2a421c8528b11d71c57aa98089f1513e3f8964 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 4cba91ec80492ab42dda142a6555dd6dcf3dfbc0..2f9ec14be3b11adfb7526b0513196e333078ab7f 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 319be936c348ef1f0c09ed99d243e4d04efb8005..fa31470bbf24aa72582b37d56879f16081fe6eaa 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 060a361d9d11b09303d901cbfa7dff896d5af1d2..024c3053dbbab673d4d23f7e78726022b03620b5 100644 (file)
@@ -1042,20 +1042,6 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                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
index 7675cf754d9090f067be7c2d1eb24a74d81d7ea3..f8f0220b6a665a1c26b9a2e15f12cb6c4fb37f2f 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 9d54aa37ce6c7074be56e99a14bc60d0bc058edd..a5d75f6bf4c7eedc96454bade72dbc9fe88af74d 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 708dea92dac8c6037dd1716e3d1bccadf346abac..a229b94d53908aa35ff3f2d8d1fa3532df4c2899 100644 (file)
@@ -1061,26 +1061,6 @@ err_unlock:
        return PTR_ERR(blkg);
 }
 
-/**
- * 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 a1e228752083f411f114cd990fa4cad546e3ca45..e0a094fddee5f3e16b660c8cab189987663cb7f7 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 aded260922684061047a2bceac0aaedc0d5ee8d8..9dc53cf9b1f17fb8fbefe6cb647f8b57f76d4c44 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 d16d893bd1959ca7d69eab2b011faa13c8e410c9..378b18b9bc342a5aa9afb4efb8cf180f0a1edd76 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 364b9df9d631ff672a8fca0b74ecda0fb5b4ec11..d7f43d4ea925a0dcaa1fbce77dbef3b81fc4bc62 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 808f2b3621068f6db28e7c3083f3176aeb111c09..495a2d1e1460eaaa3bc0e8c45be9660ba8cebd6f 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 08bb9f2f2d2310367c9fde629aaa62e8955bf0e9..5e4a8860a9c0c57e5cdcf64b523ec6d9d40baaf7 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 e9bc9fcc7ea5cb8213fdf73bc855b86f2c947341..b2dad43dbf82962b76c47c0a87d44bd15541e1de 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 30d0523014e0d49e0ac6e16880a7bb08ecfbef27..6cdbf15312387f93455bafb2b816e691def1cb94 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 7c532548b0a62d8d0ac99d8d052de4a8d045ef18..cf6b6b722e5c91612b93a52e59b27e06a4aa8877 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 e8c5c54e1d2657a1394dde3bdee52b443d32b2e3..4c5d99f8781361867344f3f49ddc9f825bcc285a 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 a74d03913822df88989b9b0198da99dea490eef1..c02be06c529950ee89a08bc985cab6531f432342 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 56887c6877a7b519c2bba19f9c15c273d6035eb2..f4d1597df0a27152dc80bee29e7d2820abebcdc2 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 909e0c3d82ea443bc5a34c3e085fa7835f2df1b5..cda12933a17dadd1f25c676e4414750175ad4ce8 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 2ec47a69a2a6c1d061d1f94dca7d7f7be4421d57..b23b0b9992322419d709eca2d1711b55f0f35658 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 b9e1547be6b51e1ea60491cfbdb9705465ec6626..5620747da0cfd7e75d0af923fe749212cf14938b 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 fdb457704aa798437c1d56ad7c1a3de9a06c36ba..13696deceae8e7fb73862ea99d731a58fe647f67 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 6640a14dbe48cf137f2ed5212e699888730cfebd..22bf553ccf9df35e61c411707a78373f4ea8aa38 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 8af2cee1a762cd1ad1092cabee4f0b757f2f4ff9..bb0343ffd2357fa7ac1c7490b3d39a4a152b944e 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 0aabe49aed09449b153de865adc739dc8e22eacf..a9d4234758d7d42258a6686866bb20ba7aa0f847 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 0ac34cdaa106932fb797c534dae04273d26b8aad..77fe83a73bf480815e3aca23678231fee960235d 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 0855f3a80cc79ea8ea6933192964e02c0a2ef079..086cf0b4955c2ec5591e740785abe658452853fb 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 0b03cfae3a9ddcae4c7906edc77c82ac40d30c6c..b71515acdec1f0eaebdf865fb184cdbed40d27b8 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 0de1108737db9326de1507dc8bb7b6e48b5df1c9..ff7e3f727082e261a5990d332b16bcec6750ee3d 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 25b156d4e645f6daf4edea37f16cede5ac3ce4b9..a6dee4a3b6e48eade40a187be4b195cf0c7b17fe 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 b68e200829f202d78f49af69cd20c291f0d92022..6a11239ccde311e3839824c7377bb5fb7d20ebe7 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 388bdb94f841da0a153cb024346832d282e853b8..d3486ee79ab54ebf186e94deb7b37d759a553f76 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 3fdf3d494f0afc305c0212fb57914f1abbbf498c..281191b55b3af5b59a43384bb2d1949d7393e98d 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 5c458199060a6e9557bb36b02fb488bb0b76a1bc..3636c8035c7d95e12012a2e9ff0bb40dc659c50b 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 38424e63bcae2e5f03494e58ba0d24f4d17b8765..7f59fb8da0337c64bb04cabd00c2de8efe2c05b1 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 e5e2492b20c5e840cb999142c70bb4360edc2035..9b3923af02a142dcf7c821114adee5522a3c542f 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 506e3f2bf53aca6c62242c0f38ab3ebe3350ddf8..83c85d3d67e355495695b278b37586869e466f0c 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 0005be5ea2b45f560a2a378a3c66b89354b3fb42..33d19c8eb02723646d48ad1eb9a864fd0bc13d81 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 c76423aaef4d7ebe1098ec63507752ecf0eb194a..ce6a5f80fb8384c810d8c0890e1a003d216cbed4 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 425149e8bab0799753cc1db9a82104fb7bb6600d..57f6944d65a6d21f4b5c87e3d1b8e4c43152bfdf 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;
 
 /*
@@ -98,6 +101,54 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
        return max_freq;
 }
 
+/**
+ * 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
@@ -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 76fb072c22dc403ef5bb34c37472bd3fc1533415..5a5a1da01a00f3fbc8ca6e2e51a8dea69003342a 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 c9a0efca17b01b9d3959cd055f019683eeceae5d..d4077db6dc97fe4dac16a7446f2d37cf060c22f0 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 d101f072c8f8ac85db7605966a979a05f06abcae..2b02cb165f16481cc7542610c0aa0dc125f1a21b 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 0101ca4c13b1a8fc3c81c59be3084ef9b7d80fbf..b7bf1e993b8bb4d9c32596bb70835cbff98f819b 100644 (file)
@@ -83,30 +83,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 76b0c354a0277ecd1cb3531fe6ca60ef3eed3eb0..de1a9a1f9f146743e1aff99fc50b36aa49a6e162 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 dc27b1a88e9343a8a029832cef5c6095a7be6238..b696e4598a240ea4237bacf42d90b22424320616 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 d968c24714125288693c7754e587f9f5f5116dfe..0d12ebf661743f7c87898eb9febaaa1aa505672f 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 2e98c016cb47dbcf947ccaae97cb11fc8fde98a6..9375e7f1242057274c70eec0f24678bdee6f0965 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 2cdaf3b2a72170c5a638530dce89007e850735a8..6614d8a6f4c8d367dcb8bb281f70514f6a054f22 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 16fbd2bc8ad1ea00d3f1c7a6c9e8df996970571e..4043ebcea5de6e1efca0a89dad8356e5c5de385e 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 f2c1b026397b9520f6f6c4ccc26d6800ec3a3374..ba9e53a1abc3affc852774537d5840a27f3c7379 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 983db77999e7a6d27800c7d42f2cd03028f5d194..52a647d7022d2bf8382e95d36419bf1e3dd326e7 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 2324695074463a9bd3fe16054fc057bb1ef7927c..f5725336a5f26dbc3082bd52a90bc260c557a026 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 3c355fb5d2b47227621c220115ebc1957841399a..a5b68b5e452fb96c24aa052e288c4880c5bbeb11 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 ba0e68057a89207df912040a37c49278b3a839d3..b3672d10ea54bfa76f01631265ca08fc0ccaa1e9 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 #
 # Heterogenous system architecture configuration
 #
index 313183b800328c11cb7c5ec8d25a362afbe7037c..ae161fe86ebb6cca838d3f5ff845dc02178b5c6e 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 7873abea4112b434d0d1def2f5d3634aae0a9f23..5c3fcaa474109f74cc8c6b589f7f9ae11590beb8 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 790a2d211bd6db21a6a04cccd4c7bc9cad0f4a60..35c55e54eac014311111a6e85b0cf3701cc525f4 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 12ba6fdf89b73213dceed7ee0f925a2e79fd11ae..62d8289abb4efb2f0654d33dc8270abf2bff7dc0 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 7f904d55c1bceb6b136b64ad0818daddd2d778f4..81789191d4ec0aebc3f0c59e24903631ff60866a 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 0f59b68aa4c245e0d7cc4b18150ddb53c741a663..504055fc70e8970046df79bccc1e243b069d6fce 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 e472608faf3351ba112a1968792be6f6e4aa207a..793c0cec407f9d36661216d55b55b0ba1fd3c6cd 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 63f3bddba7daaa50ab93dbd9a42fc13327208d84..10b47986526bd8a04b51243303b84657971eb344 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: MIT
 #
 # Makefile for DCN.
 
index 09793336d84f6944b44092fbce09e8f5d74b2283..23ff2f1c75b5ca2c7333f55d74a7a2b81b2999db 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 4b34016164348706e8be44aca42ef24d0aa89b13..fcb3877b4fcb2896c214f1bff48965a633904e1b 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 14113ccf498d27c6d9eb48790cc83821fabb989e..5b8c17564bc198de20570550863f8d5c662b8c9c 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: MIT
 #
 # Makefile for DCN21.
 
index 459bd9a5caed54dbdb1cffcbe2ea7dc8ba70ff7c..b29b2c99a564edb951c8d89dd1cae0caf638325c 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 970737217e53a18ee4331e3cc3aa570c63a79780..641ffb7cfaed4dbc739a707176e07baa08b65268 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: MIT
 #
 # Makefile for the 'dsc' sub-component of DAL.
 
index 4e18e77dcf422d0db1c76319595a897c300976fa..026e6a2a2c44cc2c6c01ee9755e8e8d206a16af0 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 bb012cb1a9f58bb515db94502a461a181c49d89f..c7fbb9c3ad6b3fe59814f2f3589dbde139296f59 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 16e69bbc69aaa7b04a458880199962199abdf824..5437b50e9f90d1c6ee27fe966b9c42771ecd4023 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 dbe7835aabcf747c25825e76dac9d2e047bb9025..dc187844d10b1f5e99e4423f15cadb6b422643d5 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 ce3566ca3e24bc9c01ea1f382fa7b80b7692d974..cc71a1078a7a69204d6f2ba295a425c7f4fb9777 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 7ae087b0504df7c7bacc2a4a4be340e017bfaf80..88b6fcaa20be0976d4ff3f3009a75d548a6398f7 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 c7c2b349858d221310da1513cf6e0d6d8b0fbe1d..2a27fb5d7dc6f0a8183a39e8f88783f73934c7b7 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 ce1b64f4dd44a9d6fa7465386c585614bb2d2858..12ba74788cceced326e655b93480d5fe876d6531 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 050655a1a3d8d9c2920cf557f3a81388c2a60870..b05b2191b919b1ff886f7335ddf423ffbb3751c7 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 3111ecaeabd0ef4717a01fe76e7488ad2b3fea6c..20616639b8ab10180f345cc2f247a67047b8e38d 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 f1f41ca8402bf79585047d2c269c6bbe40675e4b..a448815d8fc2e70bc18689bb169074f70343bac5 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 41c1053d9e38b1e6a3f24fa1b21a3c10b07fb40a..f3c3272e712a18a6fdb6e8cc255ca90d936a3073 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 f6f5312205c49ede75fed758cab856b696882bab..f56fffc474faf98868420d81ac415552973c491a 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 337ba17b1e0eeadec897887df205a7516255dad3..42385277c684325cc89a74c0237616b4b10f2d73 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 f0998f1225af15a16bd8384dcf4df903c958c638..bc3a672261635eb7540a60641bbfa24164ccceab 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 9fdefbdc35467399afc5c0709c7b5ba6fd9987b4..75dd0e0367b7a5c467bd5dee3313feae6941da1b 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 e451298d11c32adc8fedad9e86341ee308ccf8d8..2477a1e5a1669cf220ccb85b062885714c100d3d 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 bb9fe6bf5275d2eb60f1dd132b333e3ca39260df..1043e6d564df396b3ef9192ded47343b145bed2c 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 4862fb12778e096fd35ee5e71b8b27dc87a1ba9e..b19a3b1ea4c11cac83df40f5065789104d4993b4 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 04a5a0d9082393de81200181074b9683ed6bce81..3259a1fa69e105a2c91bca299dcec8d063bdfdc0 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 0f944012812304c052ad035917ffa442bd381a24..9ad224df9c68bb2aedbb58fbc0c4d4387a95eada 100644 (file)
@@ -254,6 +254,21 @@ static inline void intel_gvt_hypervisor_dma_unmap_guest_page(
        intel_gvt_host.mpt->dma_unmap_guest_page(vgpu->handle, dma_addr);
 }
 
+/**
+ * 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
index d5a6e4e3d0fd7a10f6685d5e8b0365c915eb12fa..85bd9bf4f6eee58b3c00e567a7c5286a017dccb9 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 b9eb6b3149b711cea3a4a1673c5ae6bcf7c7bc23..d034fa413164bfeb3f68bdb9bf18a17ce131405b 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 65d7c2e599de03718c3466f165b75183b2d27ad1..2ae14bc149317afb65d2b8d04bd6fefd9a1f33e5 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 73079b503724ddc92481056231d1fa0e217a969f..4fd3d76db346c1023b5f584b0fc0e5b6cac8222a 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 bbd71af00a913325a7e0990c4e3dfed097eaeb11..765bec89fc0decbf7779c7475247610fc9dbe1b8 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 010d67f48ad9448f96887a22c9bb81710d976304..247a9671bca53715c0650ecbe45a61d151c84fd6 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 07552cd544f21d29d1fce2051829d1c55fe3afee..8538ee7a521de21b6006304e8577865a58498efc 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 809bff955b5acecf0c28a4f71ccf50a1d414c7e9..75ae6f4951616785378267b2b4a3824c5409b52a 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 d6214d3c8b337b5b6ab4c1f19fb17fbca003f41c..ef4c630afe3fca0b3e8158f044103dc762782104 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 9ab27aecfcf313b04d7158d6dc6de230b9a7b91c..1bd6b6d15ffb304d38c9cb3bfb718e2964e7a75f 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 d43951caeea02b43cd740ee95c491b63d09c4e37..b113876c24283259475e59b8363cb5aef50fad03 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 43df86c38f58bcf061491cb718f66e215db40a7c..24f7700768dab9a7d715ff1b2de867eef4f4f9b7 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 549486f1d93760a51c28bf10948e62a86613c428..63425e24601896cb31238ddbcba0b9b7fae03e41 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 71c23bf1fe25915534fc0b61c46a760f500ce921..c9692df2b76cca51604c0fb008643ff26a972be0 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 5b413588b82303f805d9093a254655dad91f4d74..9a9a7f5003d3f370fe5f23926a836fd7ad0a6f37 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 f43a8d63aef86e07c7078501ff4bad0e33ba937b..de84fb4708c7ab22f4e5abbf1aa5918500b3bc63 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 4c4e8a30a1ac3cb7e30662fd4adee69ff0074d5a..536ba93b0f463510607781b4d865ff444d35a0fa 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 9458dc6c750cf36397afcb692f65e5e702f07096..f61364f7c471218ffbbbecce3b996db6f12ab665 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 deca0c30bbd436b7c1579e8d03f916c69999fa9c..fd766b1395fb18eb25985b7aad7b1e155b15bdf3 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 50920819cc1698fce981f9e4fdd104ab631a9d3f..4b17e73087643729af0ef73ce63a88ddb982e9f5 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 2dba192bf198454982d54ab9403f253e0529c652..2c04e858c50ac9afaa69964a2704573b5580c5b5 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 13b8fdaa1b432175f0176cfc000876f3e897b7e9..8bbcf5f5fb3391ce625eedbcb4c1b32e8bc9ebb6 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 0dfd97bbde9eecc4931ca43ab28496ce221fa447..ca232ec565e83a6db9dd3408b312d20e6bd556f5 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 0df480072b6ca01321af79967f22e7a63b343333..6f4f5486fe6dcccb3f9570cf3c0eb7da24b22b0c 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 6d240dfae9d9059f68737065e654bc8d369a6836..8e48c7458aa35cbbf3963462d969d2b22614ce49 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 ebf3e30e989af9745f0b5499b9c23f96f7e26fa5..e9d90b53bbc46325f199a9d684cdf9f5e12430cc 100644 (file)
@@ -204,6 +204,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x06a6),
                .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),
@@ -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 9333c865d4a9a92c780409710fa1fb9d68412fcb..9f8dcd3f83850149bbc6e75bfc11d86d8ef7e3df 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 7b837641f166e6305e0cfd4c26dba6df2dd163cf..7320275c7e56dee7ee0a6bb3af4461dc0c9826ab 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 edc6f1cc90b2448d037174113bbb42c048d77ff7..3f03abf100b599d666dbae8bf7b0d5c7ca06d506 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 f5ba94c03a8d9d59cbd9eba8b841810bd0cf50e2..e4683a68522a4502957887e475f951e5be74e53b 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 5c2b3446fa4afe8e1719c0842c1b89359433527a..2c6f60edb7ced4c6258dcc4f2791ddd80d83bb97 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 67d096f8180de12f3ec960f7eb1f74394336008e..c35a1beb817c242a0f1cc3d591e848ba15da2b31 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 e171db20c04a7bbcc8d1c2745abcf5ebf4e47b2a..02834ca3e1cede38c527e4c11dc64d0740c29ad6 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 da073d72f649f829997f6f3ca9a43c13399aba0d..e480529b3f0497cb3369bf62d6b79f57146b2d72 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 963ff043eecf97b77d7990c84f0bcc70b60915a6..7ecd2ffa3132590551591826a70c07018efc6bb9 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 45e77b308238b98af9d97216dc2258102797ced3..0686e41bb8a1c2ac425b7e8e31858060ea83912c 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 f1fb7b6bdab1cb4cae12f45e5709a7fd87cda86c..b096e010d4ee38ad4c2794ab2dd3508e963d5319 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 c605b153be410af4f4ad8fc4fd1aee17838989ed..dc55d7dff3eb9b762104ff26927fa674323abdb2 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 d416990ae309d7ba6e5bdb203ee9c8a4d6f51ddf..cb536b81a1c29a8a4b28c095a5c4cf39ccc2643f 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 11b2c7bc8041a61cdb85c6f1059020700d83bd28..a7d40c02ce6b53a7a2606b454acb283738f7f33a 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 ddf47023364b0c840e6579b2e1f29d19de236645..d39c0d6b77f1ca2bbf20ffc0865846912bbb8885 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 25f2b70fd8efb1e29de3b4d93a22a1aba411af13..43a6f07e0afe2b9ffb62e59c052e189a15569189 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 8434ec082c3ae43290961416e4f138a83317ccb9..2257d7f7810fd99396257039e897c5ddc3b59d31 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 f509c478b469d118c8c3ed66ca4b1876d704ec4f..b7cb59844ece450e491f5b18e47105c88b3b2527 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 c9d294caa27a9d8d0ec61c461b71c2e0c20113d7..50c22575aed65041c33f2f008cd38a094cc2a714 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 5774dfc22e18c8c2bdb0f8ac79daf53d6dbf4e5f..a51525647ac86bd4d6b210c75f2c83ef0717dd64 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 b0e9bf7cd150898cf0dd779a13d765a994adb6cb..d36e3e14896dd7b38a6a7c9edc6a89198f5e362d 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 0b5dc1d5928f00ebfa35920f5936d39626c19738..34055cbab38cf9032f860c392e174b63ecd47bed 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 4937947400cd005913f28ea633cb6a56ad5a9ccd..4c26492ab8a32507b2ece6858b6d1abf890ae161 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 169cab4915e3f91093bbd7d7414e30f120dc2d28..945ebce736134f2f12eeea58ab5a34a6eb26e003 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 51100350b688058dc782306a57fa81abd907612f..997cbfe4b90ce453308b109db9d48d2f7347bdd6 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 5986953ec2facfde153a3dae39e389d6b0747c39..b06f32ff5748f51b64fc24640816621719d2fba4 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 f9a492ed900b91423a8de5dd91932a370a6b2a00..831ad578a7b29d2ba61a3ed475f2c7ffdcffc7a3 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 c5d9b558fa90a2f8e85af19a8c6a7d85e3e6fd9f..e5031172c0193ad3e2906210fe2e20f2da398a32 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 1cbfbd98eb221804e9424ecabbe267f6ade8c82f..c4a8195bf670945ef017837337598f3eb0cdc8e3 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 62390e9e002362ce5fe0e4ec499591c0a46798d7..8ad7da989a0ec57f3cdfbcc2dc895d4d5792f954 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 c49afbea3458acadbbec159d251019409b8d96d8..2f9304d1db49635289e8d8db209a6cbf8141efaf 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 ce599a0c83d9583416a61f583c08742487606b60..bf8bd1aee358dd52fcfd99f8a1541c5f394463c6 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 b4966d8f3348d269e90f2c69f69d167ba613f905..8e0735a87040029f7854f70390de5596f0f88860 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 502a6c22b41eea9ded02b65a51b68aa028a78ca6..387267ee9648509fa39bac0c25c5fd6db1fe1c46 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 0cc702a70a9627a059a0ec01d6346d418c882aca..c363294b3bb93ff9ce1165c06cab466dcfa4e68a 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 0c8d81f56a306800ca0d065716e632f48ad3eec3..42966611a192647f572e059e3c6965792fe6f2fd 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 9b159132405dc750111432bb5435abcae11040af..dca88f9fdf29a10b574ed5d123eabf4df7ac7a06 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 db7bfd4f2d20efe078581530bebba77b474239df..fdd40756dbc1578da825e71ab21781be311e7137 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 41c605b0058f9615c2dbdd83f1de2404a9b1d255..c7a914b9bbbc45d2b85571611ac39839dde55add 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 08c552e5e41b2f6c96f0142db37df659ab96fa9f..c05b121104561a4cd777b40cdb97ba14838f7ff2 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 3fe50a781c1161a1050707331fa2c28169a8a917..14af1ebd853fd2048acc445e0c8b8e8a978b28c5 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 b3d89072d21c6a26461dd9a60d32eaccf68200a5..d1e1b5b56b1bbb4ad205889930cc1db9d9bad02e 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 dbcc1e41cd57dd5a669466a6907a70f78a16014f..e0c32793c24872a07cd504202447fcd102056369 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 4c68a7b93d5edab9192a3ce9c24fcdc79b7e1acf..b88d6d701f5bb26bec60314164b4cd07926fab51 100644 (file)
@@ -188,6 +188,15 @@ struct dm_pool_metadata {
        unsigned long flags;
        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 f6be0d733c20267f569b72ab14314d0565425e80..7ef56bd2a7e33974469196486bdf05c9b4bedda3 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 5a2c494cb55288e782d0fb4702d4e9efb8cab63a..57626c27a54bb5bc66be7c3832dc05059b2851d7 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 805b33e274967f7320eb2b05e1f5958512981500..4e7c9f398bc66b39b420c400769b496291338442 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 21ea537bd55e9984f7cfe5b908a3d6bcad9038e9..eff04fa23dfad46d7d43dee24cde0a1fd90f2f68 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 a409ab6f30bc33375561d4cebc20c5e20f9435ba..201fd8aec59aca67842611d8524f205d2c9b63d4 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 cab5b1352892fbd3584aec57e2180c51b01f6a23..d50238d0a85db0bf29f9ef67cd7ef23c826d8724 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 f0fc538bfe597f7a1179b31eeaa8a8bfa837101a..d4d3b67ffbba7c7b57b142efb5f9441d8511c9a1 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 97d660606d9845981666cdf54f2a88bb5e511bc9..4dbdf3180d1080a334449961a727e88b4aaadc9a 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 4e700583659bac8ce871876166cdf44ebabf4e0e..003b7422aeef612cb6023d8dc45fd440d2b8bf2e 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 8850f475a4136e47d28f94c66b99cab49822505c..0bf08678431b2a707af2fbda9194012646dc460d 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 17db7b3dfb4c2635d9c67a4d3b3d24392fcd96bb..2df6fb87e7ff9bab9ebdd3a8a7f512ca002c59f1 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 c8d16aa4382c57bd312485e5d1073b3c47ce3947..7344e8a222ae567fd3f525c242ce49a1750fe3ff 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 994563a078eb9f249b8576ddb0ab69abaa4de434..de8a66b9d76bbf93d0f1a85b1119c10b2ea2cc48 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 2870c25da166f7bc1576464f248940b8396d2699..4d1b44de14921d58e6c5f4c20e9a0dc01c20aec2 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 189e42674d8599103ea9a91a5cfaf075d705813b..010fe29a488833b38c244711c663e5f8d82115f3 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 b75c82d8d6c17064951f625ab5d8ae4309f15f72..3d0bb5e2e09b2234e1737e91cfd4354d29ecee1b 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 5cca3fa4610bce0cffff13ff18160e3f05b73604..500f70a6ee42fe7b3c4e52cda0c617172f0ec3dd 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 acefb76b4e153211c7e8dfe823ae2359590bef88..5091e2c1c0e54a17fec48f2ba807fc1a29a84978 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 3140fe2e5dba861c5f281762cbd96ef46e18d03a..1b1c26da3fe0b52dc4abfbe9d782356949f58bde 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 0ed3e0eaef5f99e09ac1e299264983d9925a38dc..fe83ece6965b1f90d8bc575507711c772a8da56f 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 a880f10e3e7039bf5e270ea373ad55b065ce7cc0..8083173f1a8f3d9ba1cb92ceb9210b8c0122e171 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 0cc2338d8d2a81216d7a91e0d48ad704b7921fbd..dfc77507b159a8aa336a18eedded4f8ec2e01a03 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 5bb5abf99588747a5738e102e559f5e4108a8181..022a54a1805b46c85819964d79ac6ca3114cc379 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 d862e9ba27e158e91afbc04669a3eb738bec765e..13dbd249f35fa346501457646cd8ef3ae0e992a2 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 fbc39a2480d058d6bd8caa47ac4d5eb3a278ea60..180224eab1ca4a46c34e9c62061c7087cd22bfb4 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 60ec48fe4144693fb005ff6c16c00437369aaa9a..966aea949c0bdc5c8d2252de53ba1d6caed9c4c2 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 c681d2d28107dd163415bc0b381b7d8508a5bb5c..68edf55ac90625b5e69e5e1009e8539281f604ae 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 d24d8731bef02727decbf530df6746c33e0b9761..317f3f1458db443d89f2e626dca4cee3b8cff463 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 be24d42280d823bbf9d20181b4731282afb604e2..a3da422ab05b6d2e46da9dc1016a351d190fca1c 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 dad3eec8ccd86ec49fb543439a36ce2f3b53a717..84c3d8d97ef6f4fbc7278044afa56c1652eeadc7 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 aec3c6c379df86b7bbe503a602ff7406d0b5758c..9ebd93e79aeb64889ea4447c47a5e631ed2765d6 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 ad34f22d44ef10761155c72ec44d58e4209aaf89..0997d352709b7dfcaba9383f43241e047a0391f9 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 3182b059bf55ce0be15487d9cbd03a894b75105f..4690d6c87f39a52ce839e35b8983a157b373e436 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 ac98f1d9689218107ba72ef045ff62d2defea1b6..455c1cdceb6e2b51e30a8ab04d1aaa65177a0d88 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 c8c93ac436d4c8c1729c833411a415805d3cde73..c65eb1afc8fb9848cad664049a62cfabad764886 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 54459b69c948481210cfd5795bd0912b100481a7..f7f309c96fa846c3e04301c9475acd5db38bb4f0 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 d5b644131cff5cba613157b3d85f665f2a29d8a5..65a093216dacfdd7509a550cff1c82235f5da6d2 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 a1202e53710cd0c7f16aa4f572ae0bc62da7cb6d..8bf1f08fdee26d0b305f4af0f4841c45b8810f5e 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 c76da309506b257307ba1de0582176bc60780d83..e4ec0e03c289490f2c96f93e5a73757e51d3deef 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 d6057748456768566478d7022b378c8ae879f185..9a48c4310887d1c15a83ac765fa439053cbf21c0 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 c80bb83c8ac9236e12821a61e9f2e03317b39762..0a721f6e8676e22f73fa8ade0345d765c3d30d82 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 8f732771d3fad8965318dca81a5e292a5310d8e6..11c83a99b0140dfb9c11e8246336d6aad0fe8278 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 95a0d3910e316b42f42c82b66b7256e671432ccf..ac02369174a991aef59d03c448928ef643a4a482 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 31d94592a7c02b1da63855d33b8896fde4bfeb24..e0c985fcaec128c6757cc69ecf16946bfb9da9d3 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 1a3008e331824c80a0aa0184d9f9e58b1d51291d..b36aa5bf3c5fa564b6c535204f7021962088b10c 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 c303a92d5b06de883bc619ded419ca8587d41732..e8a1b27db84debab0aad020a869660bc310b2b80 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 a4cd6f2cfb862cb25315823d155b5497e59f5c2f..75d83c3cbf27f2dbf867c69888137f6b17a973c3 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 355cc810e32243361de5cfc233f0d844c5cd685a..cbc6b846ded54e0e95b3d088ec952514797c556d 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 0775b9464b4ea9e20701f52a2397f8a9966be08b..466483c4ac672d877c532f6e5bd637bb64a13e94 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 1a768837ca728af9a7047db590a6ad40446f3ca5..b29603ec744c4225ad5bddd4e04dbb0f8eeba4ac 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 31248a6cc642e99f990cdd96b038724320b007b3..fa54efe3be63544dcd7f59142358854cbc7e6f40 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 86a3f42a3dcc01371db5996747b1764c3e09843c..d6a192c1f3378e46277eb77e9851e3d9df1c0fec 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 09f3604cfbf8fe3a73b409fc9021a4df686440f2..746736c83873702ee30114f5bce45b32ce7352eb 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 5c6b7fc04ea6294b6592b23b278d3b70600ea05a..75757e9954ba24cda3aa8e9252a60be1bf9cd14e 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 68bf671a519044d6cfb04eac574957efca1e5b2e..f3f9eb8a402a2e8615184ad6e47dc9b3ae8d4be7 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 34c1eaba536c05d2746c3fa3bd278d4805e94672..389d19dd7909ccfc136232eb4d51ee7e3a033560 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 30e511c2c8d017f7f168dd3ef839314627e7ee53..9ce6d30576dde8579afb4ad750be6e762e9dfbd3 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 4c34375c2e22096e8fd6ca47a5de1b678c06bcf2..3ec6b506033d8565812991f796e3ef768a969dd5 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 fe14814af3007c2ee6be5b162042d977d5e7c241..c604613ab506d3c920cf52d54011403751a9b971 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 c386992abcdb870eb3fef637f627f4abab33de44..7cafcecd7b8565fbba414f9f567e98734940edc4 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 dfe37a525f3aff78433229932afa28854332eb90..667f18f465be1c6d35e52685f29095665efba00e 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 679a721ae229aaaf8432dc7206f4adbd3f305ec6..5a70ac395d53a0f724f3f29431c4c32afa235619 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 3b9cbe0668fa488523f59aa0a12978c0c24fce18..1024fec7914c41b50d8e7087e39a5090131dd5e8 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 dcaad5831cee7aaef48758a332ae049d06ef9991..365a2ddbeaa762f84a51106163cc915e2c2919ef 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 dce59459ed41b9867b3645ae2688d62c57c1d52c..2a47c6c5007e1280a320f9776afe10005e23b98a 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 b50b53db37462499cafc46c40a0fe77f7a52095b..1c50af6219f321360b05b729a9f382842b6fb46b 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 a758bb3d5dd49fbfaee6e79001726a904b644261..4df4ebde208a0465dac1e975304fe4a6fd358c2f 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 d93891a05f6033638916d7eda0a560110dcaf4ef..3371e4a0624838516a7ae6bbb62862fd17eed711 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 d9b63bfa5dd786d74c3a14eb219f441f589050e0..94af6f5828a3dd2885b5f9ba6372d7637b8490bc 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 773128f411f1e93e57059280221fbb4cad7d86f7..d704eccc548f62d2a1317ecb0e972893eb49c1e0 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 3bfbf2ff6e2bd58cb242e4891dd23d9192aa9cdc..df0ef69dd4748606391b339e7c99a661fa3501a9 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 c6800d220920ecb3613789ac094d8105ae0cdd94..bb07024d22edcc4b0f5e00bfff648cacfb5de0b9 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 9ffb22211d2b007ff70cc99d4caf5403ef0609c3..55141d5de29e60254165ae1b269c31d9bfd36331 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 582fa8a755598d56682a600499a9875825ee47dc..60527b93a711539afc666dbf0e1129a0b7454e36 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 24e0e2ef47a4dbad8e6d70771cb973df6ccfb03a..369e04350e3dec7b29309e1b6b4deb64ef7bea9e 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 e914f6efd39e87b45648512293e2269db0b0638d..9503ddf2edc76a2dda40168b818c3f3e193e983b 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 61753b648506b6f59b643647a2cb82aaa60eaf53..5d21c6adf1ab6de9647a25d3fb17452d5509b2c8 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 9579a706fc0823c847c72937c4054409854f9995..a881b709af25633274690daea073b13cdc61609c 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 48b112b4f0b07da494f6a978c3a9259f6cd94406..9b11ef1a401f22961d6a99382d3d0522bf082b19 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 07d1b911e72f8eca67d4a1d1b4487e9c64f3dfa4..52ef1419b6715d281c8a72b2151b5e614af78c85 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 679ad3d2ed23dad04fa8d655965b968a5ea1644e..03d79fee2987ef24e90ea06c81b313fe16d1c86a 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 e57fc9197d62077b6375006e19047f22bbff3b95..ac89a412f665ee11d7b6588b86a0bfa73b25c32b 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 4a91be0ad5aec0536f8016ea5c14187fb95b9944..5c12d57be0405dcf6da00f8d0e941d2dfc997293 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 bdc07739e9a2240b058525eca66a21d1108cd110..12d6b8d2e97e82297a31c0e682cd5abe3da2a1b1 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 ca1d49146f61143537d55dd07511866a673e4ad4..7597c70e04d5b42b54d18a8c7de022bc7586b99a 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 a608f445dad6f8cd6a2f9bafe00af917b86c2130..f213264c8567bcac5bec4a9f631c46de4190f8a0 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 bb406eacef829aae62c959e01102cf665d48b7b0..bc4158888af96e19e72dbe6cc2065c83a08ea149 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 6f5290fabd2cf958e68d8c975d5ddbecb54be0ff..458db34239a7ce3c55b7cb4882920fb62ba27f38 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 e36608ce937ab67a2481e6a3616031eb28d6e671..33dbc051bff97f3525f5e9e736f9e2ac7bc3639e 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 063dccc18f70a04ff362a276087637cbcb0c5c76..5f9f0b18ddf372365c0df1b2916d408f8755e836 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 0d044c1659609e6b39abfdb2fb9958428317f414..c4e4b0136f86e7d86e784c831af1106af846d615 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 ebd47c0cf9e93fd6a9b21a05e3bde6e82f6b8d73..70b99c0e2e678c4767af956704504ef39fb2276e 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 f47b4b281b14ab5ed05973faf00c2aa09ec5b7c0..d7302c2052f916f74c909a3f35941e5e79b3c68e 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 d4e1b120cc9ece1a6e4dcf265cd6ca56f812dd1d..0ea03ae93d91d7bcedb7870be83d711217b9a082 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 db4a04a207ecee98a15e702f18cc20d59d52bcfd..f6c8963c915d4aeda456299cddc62d4f7b03c811 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 ae97e2f310a36bbb0802160b7db8af9f1b4b3b5b..d7e7043f9eab283c69ed417da79a28ff5e5f50c0 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 99f0a1a08143e0864e0ba69718945fe538ffd447..cbaf178fc9796a976b1a008afe6c0a5f1c73062e 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 460f443f64716852cff956f7fca3d87431ea2d4a..2edd9f7b30742e990a879d1a6e6705a1e7eecabf 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 59f6903e5abe3188aadc0f1eaed1d64ac3cd41e7..9dc09c1174169b6b5f5666dbaee9b62f76fcf627 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 6c28f38f8021a7f0ef8adde275866155e1e30738..aa5204163becadc2e88133779eefaafde4e79103 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 b25f87ff8cdee65e9739a65c5e7f4a26d2526049..8b050f0b43330543f365a4f8e83eb2ae67342813 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 2601d7673c37dd9070d5b94018ab9a14054ac94c..7b8a6bfcf08d97c1cc1421cd67eb53dfbd8ea9c9 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 0cf94f05f0080623ec396ace7932fdc27efee40e..b7c1108c48e208f2e634309acd84d46b182bd7e3 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 941aa53363f564a23a15cc306abff534283659ee..bfcd02fdf2b8915df121562303e0b9358b836f89 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 f2d5115b2d8d19c47aa41b23aee0fd491e5b81c0..bbe90354f49b09488fa2a3b126f1941694fbe7b1 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 51b275a575a52b37ecd0659c88e763bfaf0de2c9..68c14143e50e4884f4057ad6071b662d9bd38378 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 042a24314edcfd476f11183cf0cfe05ebd8712c3..abe7f79bb78954b2eb5005e20821ebf3e0efe880 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 8c674eca09f1368ef70618e12b1a4f9001d2602b..2323432a0edbcd07345235263a9bf8a610817b97 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 417b868d8735eab8cf1a6dabb669cf0a0fc875a9..ed8d9709b9b96ef4c70feb530bc346c50052bef6 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 7b7ef3acb504c06c95849212c5879a7931ffecee..412ac56ecd6025e79cb5b57cc07fed649091b5a9 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 b2af04c57a39b3f7675b83de97ea54196dde0fab..6feeb0faf123af11818f9a84207102d67d12e2bb 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 baeecee35d1e1229646ae0199d3d37fc023ae1b6..53dd87628cbe4a26997ceaf725ad90dff93418f9 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 c36587b42e951eab806d4e9a12715db175619a8a..82a0ee09cbe148cf2407db213bae2cfec55312c1 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 d12e149f1a419ed72ef65dd788d409eb68c00cbf..fd6b9caffaf0c41ca36434a7ae90538b319560bd 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 a92aa5cd4fbe8b1fd4433652e14ac9cef446af92..76d6b94a7597ff9b0686f3ac81c989f1fac711d2 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 114801a32371c8f734362d3b550890d288943027..fb4159ad6bf6a8e5729f79baf27f0f68078eeff5 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 c36bb1bb464e60de23c466d700cff0c3ef1f02c6..8c5084a3a617b1a6839959a90f5691a3a2e45c41 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 16b6b2ad4e7c0aec2c3d58f6aa9ddac6f6d9dd32..9071333ebdd86fe290f441c21b4a1a37c7e40ff5 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 2ee1feb416812faf45b50b0e3e74dd9f1dde6891..6678f1cbc566078a7681a4aa047bc01a80cc4456 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 3cb65371ae3bd45873f573fef70de052dfca373b..66dcb61285392523d9b8c08739026fb9fbcc5ee9 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 3fffe4d6f327f1ba4c2ea3df8c681811f1c3c7e3..f180a8e9f58af6c331805ec1ab80d29cd0112a5a 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 4bdf44d8287996fb9a07af330316744078cb0eb0..dc62db1ee1dde83b3dfd550bf1cb9eaae5a3ea25 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 2aac1e000977ef5e673e7d310ac2c0cbaae6e7a9..51c665a924b76cfb9b306af51b4dabe5a933d0d7 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 d2d3447083c7bd353a4d030574b31b72d8ce6309..794000e7bc6fae09ec157af540f34a6fc0ff9070 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 6e481908c59f642645824df070eb3efc7266f3dd..9f91853b189b01ee71143b1932ac1424bce6a15d 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 e763205e9e4ff5252a37610a84faffb7404a08f3..f61e373c75e9660897e7f1557bd1ed46353f6655 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 27cc8eabcbe9dc598561087e9d9555d0098b31a8..76b25df376b8f0f5a696e188652da0d57abffae6 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 ffb84987dd867fb5030ec56bf2cfc261bb7d605f..d3e098b41b1a4698878950299a4cf2273798f42a 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 fb395cfe6b92792fbe7e02e4009fb1e8111dea2f..f20ab21a6b2ad9ccffe57c06ce28122d7efa741f 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 1b9b43659bdf4159ab12af55d6a9a5b96b2b6087..a20c0bfa68f387dc69a48fe8732eebabc0d4a5be 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 5319909eb2f6e81cab72ac3da2eb9fb246addd7b..e7f4ddcc1361938dacfa81f7e32160eac74993eb 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 a6886cc5654cede0dcf3dbcee370fd7be53a18c9..56d116d79e56aa531a6baa9086149267e128b1d4 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 4fac9dca798e812d8f4315baff14193fb6fcf13f..a7cac0719b8bcb322ed6af3ffa2e925352bd9572 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 ba1288297ee4b747b6c741e1faff5a83a08db26a..a87562f632a7ff07a4f7fb405dbb66ad4764f0da 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 02148a24818a603c402963e1db1326c75eb87258..4458c1e60fa315f92d0a07b3999a008430661e5b 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 b722e9773232bea3ef1bcbf38499edcc8aa653ed..b13d7341f8bba1f523aa74dd77f60d51de5bc4e1 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 29faa5640516d1020c728d056a3b8fafd4d2c709..0fc388db62e0dd0343869ba32c08cadb5ea7c405 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 bb091e395ff5914f754facd9be9e476aaef7991e..9be74881c56c98c4f6010bc71e101fcbec843b46 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 986a2ef678b9341dfe27f34ae212bf1fe3d3d099..3b47b6c21ea13ff2697a63b0205c6ae480584c13 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 c7ee90888f69c21c4e8e3e8157d6fc43202547d9..680fed31cefb02b6771d5b531f7080f1fb4b05c7 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 29848a202ab4e16ccff65afb48ea88623214756b..471dd15b227fe7a9b3107ff6b3102ed4e0d16869 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 ac136663fa8e55fb08ece4416b95f52fa30ebe65..082c16a31616e10256658cfeef87a271b4d328c1 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 e877b917c15f59fd6121f1c4dcca420aa2092520..30ea37e1a3f5e11021967201bd3f197030259050 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 59b79fc48266e6fa087b897c1ea590462a33f7b3..79b27865c6f42c7342274904db052c138fa2e61f 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 a8dc8af83f39a354c1b2347a59033ef0dc0aaffd..1ba9bc667e13631328c590f484683188e7d74039 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 1cbae0768b1fda8c3b07729b08c39a545a4a80e3..f6c45a796433de838949ccf8eb4ad5d0ae441ee6 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 b0a6eb106edb83d330e484ce9777d4b96fc350da..7c278278573634df5e0e82833ad6ff827ef6a13f 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 31df23502562383ddfe2cbb0e0d7d98865ed5d21..f60a59d9bf271074dfde293a695ea0d8558e91c9 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 044c3cbdcfa40664497d13bd00e607584eff99c7..5023c85ebc6e0002d9984ad8e24090b8531a7c8b 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 8b0ea8c70d73040bae8a09f85e7f086ce6afc0ad..635cf0466b5921c103bcf1b1c5bd657cf32e7e71 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 dbea28495e1ddb49193c9acae8b15a8f08cfb0c6..4e12a32ca392d3954489c9d4a441ad0bcdcb7729 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 87338f9eb5bec73279acc5e679290875cd4a0072..ed204cbb63ea19719c4a72c13dd28987dcc26f1c 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 281568d464f97d2ffed2618207b3e8737f7e413e..aa45840d82730ab290f656ff6f9c46a278470972 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 0eab79f82ce41bd107de6e2997543a0aabfaf3a6..da923ec176122210705bb67cda9c81cecf83b3f9 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 023f0357efd77eae3182aaf596120b8a8847fa8b..294276f7deb9e3451e191d769b960d3d143a5b3b 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 3996b9c4ff8d41fd0f46ebec5ab293661fc89dba..fd1b100d2927eecb57c2fb86f1d52ee24bfaa57b 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 a9aba716bf80be70c3a8df033f8e468f59477560..0c960a97ea0214ed73e5fe018587aafb6c8d3d8f 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 6ce044008cf6c4197dda79df4f5f1aab74b846b9..460d5d7c984f50c66ff6bc821cea526986008d2a 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 ce1d0235969c369ce02bd2c5fa6dfbfb36a8a549..0bbccac94d6c5eea78050d67bbf42dcf5f028842 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 d48df36622b74b565b037d5ce56d95dd1b150162..0d8e4a364ca6e0d54d01fc644c4907287b88646c 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 aa2f77f1506ddadead56753697b7d7c8a494c592..8a5c9b3ebe1e74e982ff49060e48f1938049bf1b 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 b7d23c4387569e290a7482389169aa932312be7f..7a3a29e5e9d29d33bec4e9ff45e50f26986dbf96 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 e16eda6e2b8b22b768387a5c0c2a5091c4573059..3b1388fa2f36e74093e2dc2abc0083cd650266c5 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 a0025d23b25735b86dbf12eb1838130627319e61..4917c5b033faccd0f6b9fe903dbf99cb8a47d62c 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 6475c3d3b43b660a6bc7cc06ad994fcf8f46fc40..d23f7408c81f1e4409389a5b51b3b05ff93275a0 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 6721d059f58a1a849d1acaf983e47647bba7698a..dbac0fa9748d5fcea4bbf44ce610c4ecd1d5b5c7 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 dc6f62a4b1979e8037422fae9163e4edcd344185..13d8838cd552be01b145e0d2f78dc815c3ffad0b 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 6f5edb9fc61e024cc9549497c7d2629230b585e0..d8d157c4c271d32e44eb923bccef4dba6cd4192f 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 4afb5ddfd361f29b7506272bc270b02592aaff5f..e9437a176518a5f137a4df32d393b483e6d3b23c 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 ac2b4fcc265f65c10a128bcf092de3a134319dc8..f48a23adbc35ddbbc66c5227d8c59e3413791b05 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 8273126ffdf4bb03edfae115973ca3562a3a7104..63a00ff26655e3e4614ce9e745b40d0ee4d03b39 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 48a439298a68fa8533df50f6e65f0aa7809c1b18..9690a5f4b9d611b26680f767310e5bcc34892b5c 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 66a4dcbbb1fc9de2c5f160497926848ace8bb37a..f4c2359abb1b0015af491daff990b5dd9d83846c 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 7ece6ca6e690b23e88348e55e4c38b710dd5515d..91d62276b56fe4d883fafb00587c2a8d76d2ef98 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 72481bbb2af39a79cda097ae164bb5e96111471b..5b986d6c801d9413b6bd40381b55ae12c3b97bbb 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 6532d68e8808d03ad2ef4126466bdb547c4ffc66..e4b96674c40526c75726c9b5c53a81d427f83d14 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 33f8972ba842feedb7837854a78d281a73c9cce5..00fc98741c5d1176bed0cc399a5e1e6e39a8cab5 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 e05679c478e2b3b22b3d9048d0c5f866ef2ac5ed..93f995f6cf3645bab73cfe6def29c83a54b2e1d7 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 4f2e78a5e4dbee31147978a228646b30e6ed8d28..0c142bcab79d61d50e67a97862aecabe7c0542a2 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 49b381e104efaf64469c75e35668e10efac4ba4d..7b36b51cdb9f978657ec1e6fa00c5d6ee2b13b6b 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 d75a2385b37c773773beec66b16541b8cb0acfe1..5f5b8a7d5b80b998425dfcd5cc900d5ba4855c2e 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 c21be6e9d38a6c91ae75fb4e08a28588c1164df6..378486b79f96aeec8e308f5630f9ffc168ae16a6 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 b0bed4faf44cc85a918a4fdb8a3929b846c13ec8..14876faff3b03ed33c7855db863d9d904e94a329 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 a7d90a719cea6727259dad81af433bf92779aed4..8a1650bbe18ffc426acc88b65397b99f1c714d63 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 4150280509fff56775318ec3007a4f03c5b95454..7503899c0a1b52e2806dc7c76aebbeb4b6e667ee 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 f532d6d3bd28c176b69fd42ad431bdea579adfad..79bc5f1338edfb51e98f67ca47e167c32c903f18 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 fba2ec3a3a9c904a8d592c3a4141e9f9214eb385..468e1713bce13944719bdae1cc13611d0693c343 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 1686bf188ccd056c7453db63557efddceaf08833..b7f3cb2130caee38a6458d3d81422f83637698f7 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 488641b1a418d1b0f27aa3d17925b9e5a1a2cff2..7f8a9b3137bff33f24ff4eb058a5f77cf01c4244 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 75b6d10c984560c437a91ebed744b9f3d5510c4b..575636f6491ef6d887180f9fc3c36740d410083c 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 5b6e86aaf2e1a42f468c0dbb94e8231d12973d1e..24658b5a578708f8b649a634e0503545e3930881 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 b2e8fd8a8e59922e81b5d27bbb04633e8d9ef297..54efb21c27272685c11dc70185ef0a48c5146dd1 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 153f71a5bba91975fc17e528769b8992016819d9..274318e9114eee4cdd95108d6fb309c16fdd4678 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 eb8bd0258360f95d7d62148b122cd07eadfcbc90..2f4802f405a246e71d9ac2602b98ef494a535f0e 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 3270a40b0777bf3c0e68b917f25155ac09d1eb8f..b1bfdc5c1387aeaf2a449d702698da14206e3b72 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 0cb43b6827897b6569a6d9f7c1d555bf8afa0347..8d47c76b7bd1073dea37b7d945211f311c59642a 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 56032c518b267a5b3ce3875b0e4081e1bcbd761c..e3c76645cad76ecdf324b9613cbba36e185a0522 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 a1ee0b775e652b16f9abe3134e3ae2226ba3ab9c..18e328ce4b54964a6dbbddbf36450e24bf77460d 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 93aeb2e539a4cf6758202b4137a4b595115707a5..d4282e12f2a64a2e3c1fa696d00c9862baff6861 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 d897a8e5e430e5c35702bdb05f227ba49846ab0b..c58245797f30af0c87b12e2c81fa98e4cbbe5a30 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 ae2db5eb15499f54b986584f5218e1e257eceb47..091e5bc8c7ea93544bd58cefcb8318aa2fe43a44 100644 (file)
@@ -7083,12 +7083,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
        send_root->send_in_progress++;
        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 1a846bf6e197b3f6bde759ead2735841b1a78700..914eea5ba6a7adec8d97a76b6971adfa3408b20a 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 09aaca1efd62ae9609cf72d897a907e915bcd02d..ac035a6fa003dda0d9f4820f905e0a58df26d1f1 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 493d4d9e0f79c8292b4efc6c3b5632ed91b95cb5..97f3520b8d98d29b61abc27a6751979854f1c349 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 6f757361db533ec6cbd306cf5b92cb0e1c96c771..d3f115909ff05a7deb495f69f3261624e92b2f91 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 91caab63bdf521e5e16f30cd0e8428fb7b242a3b..76b84f2397b1bc75167e6db1d433674c0620760f 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 d8e5560db285a0bbee1e7ce5e52d224ce35b08ab..a6d3f08bfff37bae0676ee7f0a12892dddfb48c0 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 f5a38910a82bfb94d71ceab28af196b3d0165c6f..9d09bb53c1ab4a36268eb583690ef37b2f08387c 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 facb387c27356f99864f25e0c0016752c70261fb..c281f32b54f7b6121de9dda389bca07fb9395042 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 068b029cf07390d1495ae3feffa1fb16d3c5872d..374db1bd57d10b8ca74c7081c31744a850fad612 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 5cd131b41d84f4842bf11ed3084d6700dae5112b..14c7e8c49970adb914ff311c14906e4c84cda1d4 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 aeec1d6e3769e41819cb6a46cb593a4bee68d2d0..471bac335fae6ed51b8db1f289e7ec3b94244450 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 9c9a7c68eea3be1191aaa6e0616138c0e6b10d3a..29a795f975dfa346e62aa29b004c792a9d830ace 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 f0f9cb7447ac9bfd6c7cb6bd312c2676b6aaa543..3bf1a01cd536dcf1330fec6d7d8a89102c5f6c77 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 fd0262ce5ad5b8ec55960c271ad72c960a2763c1..ce9bac756c2a1a5a36ba0b3d8a4715fded4d3bff 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 4f554f019a98984fe3a2914d2f1365da6e82a6d6..cc86a67225d1b87fc56f57dbd6e0ad700edb18ce 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 18c7a33adcebf36b7908566897de44a1de683c46..5ef5e97a6d13eb8171c5b49ce2f02096dc18a391 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 a5c96bc522cb3e3afaf2f8e582aa586f5325cfc0..6250370c11702b1346abeec4a971b8ff6d07fa16 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 0ab6b1200288e304b0e9b724985d8ac3015292b4..9434f6dd8df327a104a2c427dda36bfc1f553718 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 a18272c987fed92ebbc0347c3e68a5565499ff23..27d29f2eb6c82f619331ab44b169460b777a86d7 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 040df1f5e1c8b1d1f6f0bcc766b1e4918ab6e839..40cca351273f4c79a093a1c8aa5117cb6ca2f8eb 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 a13a78725c571372e2af4ebd9dc204eed8a1cadb..b766c3ee5fa8cbf955d0364687cb9cab97a92eac 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 92a9da1774aaad37e9d51dcd61cf821d67423a1d..bbce1c328d8557e177f33365600085e5610afdd9 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 3da91a112babe874af392635a32e971d8885937f..2f4fcf985079d52400e7d58b732b7b189133b36c 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 74b40506c5d916324404af2087395a72c2e73fee..11e80b7252a82cefaf12d56e792f9b679e2f5a13 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 7c333a28e2a7e9874f27c85492b943b5d33fc935..3f5e356de98050f67503336cfac1db64f455230d 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 405be10da73d4bb37b2fea9a3ca9f9247e01a5b4..6f084e3cf835124e4c138abbfcf5c217a0893693 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 2fd0c8bcb8c147f28d83ddd883402e8a40a3b7cd..be601d3a800807360a0272c713d4abfc25795687 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 b801c635310098bae2ba074bd66d8056c2764140..6220642fe113b69e6303877898bf53b04330dd90 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 702aa63f6774d75416b245656887394914cb26f4..29abdb1d3b5c6cf235e99e81948ee55b6d676636 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 73c9775215b33ba043468f57d6cb618fbcffe477..70e55588aedc74d966208f1b819335f6750970f3 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 bc14781886bf0735fe9cf32681ab87a3f2703efc..b045cf1826fc4cb26d577d05916ab3545577061f 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 c269d603352532057d278e88bcdcd2cf6ec33861..76ff6633917350672caa413964da6700811e9af1 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 6934bcf030f0b53ff7292561cb25fe14b7295158..f283b1d69a9ede9f33e65b61177c27fd9dd049ef 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 a8279280e88dd89a5acdbda5f7acd179d5b81569..28348c44ea5b2a808277598bc6206168955d4c50 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 afbcb116a7f1b8d1f26eafcd94c7064bd58b56ef..7621ff176d15ce6920170f6c5064e63f07816522 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 87109e761fa5e3f8e994612e774bda07ef5c58c6..57502c3c0fba1bd8fba06693a2c0401054d5c00e 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);
        }
@@ -559,7 +581,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                }
                wait_event_interruptible(pipe->wait, pipe_writable(pipe));
                __pipe_lock(pipe);
-               was_empty = pipe_empty(head, pipe->tail);
+               was_empty = pipe_empty(pipe->head, pipe->tail);
        }
 out:
        __pipe_unlock(pipe);
index 37bdbec5b402008c89413fec3c8ab84e92e006ff..fd931d3e77be5438ce2fd287a0170a5d18adfd70 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 eabc6ac1990641fc6b4c54108d32328a9bee95c6..b79e3fd19d1152388c1972191f0a525a71a8c7f6 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 19394c77ed9955ac0b949f8a536f9ed4fbbace08..e4a6949fd17165979616c4f361d2cf4948703007 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 92d5fdc8154ee9f1e2ec38b8a78b9b486240bd24..31b1b0e03df8ccb55b33f644ec0d2d9a8427f81d 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 2bae9ed3c7831cfe1a22e1e33e411165c520d87a..fb376b5b728190807fc5fa3c30dd10cea6577041 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 e226030c1df3c3f1c333f2acba8955a116921cf6..96ff76731e93df766d09394f8936254849e5b9b8 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 99dfea595c8c79880e19740ac088d12b4b306671..aa54586db7a5522d80c879df1190bb45647c3230 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 a141cb07e76a7f1a4abaf4793d66459718c65462..345f3748e0fb7b090b78632a22a39ca8a5f72077 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 7247d35c3d160af210f35e07393fd04da361326b..db95244a62d44db0b7d921e4a3f66ec5cf2acb39 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 d2f786706657b1f075f9091761aff0191248e9cf..582ef05ec07ed8fbc69e38a69c714420c72f9066 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 d77fe34fb00a0c23b36d6698ab385ea9553d282e..aa5914355728686ff76b31a014cbbab9d619683a 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 4f404c565db1baa7688e3a4527b9523da009c64d..e18fe54969e97ede27c426277d84601d0c6aec6b 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 7ed1e2f8641e2f2d2d7f17266480b35450338f22..538c25e778c07eec9d26fdd1585247fe81de4544 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 c97ea3b694e65b5b6b48d861d9b98ad388fae6f4..80a9162b406c26c702f15e264e0bd3083cd4636d 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 10f81629b9cecc71fbf3bb0d906f6389b2d4b963..6d0d70f3219c5b80fccb2314acf0d2bc8de7f129 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 3d507a8a698929f6a2cbab4ebace6bfa9f21847d..5c4d7a7551011da675fd47f996ab73201a988a7b 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 0b938047514445e3b017f93589ee1e55d74b4555..8cfe570fdece617e997da7ce3950544e6e4d9c7a 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 c09d67edda3a108eb507e02a0b1f7b0c1d68410f..1e6108b8d15fc22a2dd93a69d02028606996d831 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 afa940cd50dc5355bed0815c0d7a0c20a548fb98..cc6bcc1e96bc6de915ed5044874f82cb5fda790a 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 d0391cc2dae90611d9ec91187342202300efc01c..2960dedcfde8a25ad53ed7f15d133d7c9fdb4757 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 0d6e949ba315d28920ae43f16a77c4f5bb3dadd2..03e9b184411bee44d8be375bbcaefff5f72509a2 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 c41833bd4590c10f556a94cf93b1a6f1338ccd96..4d9a0c6a2e5f35caf95727449b898c0f832bb0eb 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 af645604f3289957c420ef2d9d0fdbaebc84c0f2..236503a50759a7229b9e9ee31ac99a0f2a7a012e 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 ef58b4a071900777170685221cb6d3f261cf709c..1c308c034e1a6835cd9e4cf9b2f4069a58060a04 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 44b5a00a9c64c8150c8eea2616a0a5b0e69223f3..37f0fbefb060f3dd9773978991fe131e80dadf97 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 7281895fa6d999ba1fe2b67cd0ff676cb7fbcc22..2656155b40697846db4b8f8f6fda49e5f242d7c3 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 22be668457bf33ac3af452563f001684e26c8c0a..8dff68b4c3168a75c762e31e8fe91abb519554e2 100644 (file)
@@ -2310,7 +2310,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 cacb48faf670690f67fe5c45c79fa242c4c7fc38..5608e14e3aadf893570e4189c81cb5472a27e184 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 c28a1ed5e8df9f4e82b783d0ac787606763c4258..26289679982647ca6feb176624c1db65948dfa76 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 eabccb46edd1264250320891f180ed7243ae990d..a3300e1b9a0100ab8660d5e127eae12ab13c93c6 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 3f40501fc60b1d9f95a7455ed0d29f97d8bd9571..2af7a1cd665893d9ff509730c73e0e0852a6881a 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 869c816d5f8c3097b09298a9d086e7f75fff540e..24228a102141e3981911bba20712ca53dcb2b219 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 af9cda887a23f32d64b989ced85f8ca2928b0950..0ae9cc22f2ae255c55337812b121a9a2d2eec9ca 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 a9c6cc56f505e6210356b0c8d94e8aa90dbc2aa7..dab8b1151b5698719cc9bbb072cead21c8773181 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 91f6ebb30ef041a8667c18b949ccf42e976174e1..1ecfd43ed4643461af60bb47f5d4f61aad9b12af 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 d126d156efc64e7d2d710197cf50377c12ad620d..915eacb9c059dd778c5ec6c19a66328db0a61968 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 9f90d3c92bdaca011f5645aa326fab4b09166d70..4fb20ab179feea2dbd155caa386389ed6144c129 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 6bf605dd4b94f0b33f09384478d4e3379f269176..33d01866bcc2c014ace7faddaa0b4f6fbee8f8a4 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 4ff86d57f9e5309905e7e5cffe5a1eb875b45e30..a1f8bde19b561a03ff09cd817d4013512d7f5383 100644 (file)
@@ -10523,7 +10523,7 @@ again:
                goto unlock;
        }
 
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
+       list_for_each_entry_rcu(pmu, &pmus, entry, lockdep_is_held(&pmus_srcu)) {
                ret = perf_try_init_event(pmu, event);
                if (!ret)
                        goto unlock;
index 54cc5f9286e93ee708fea396651ff3f53d1dbb1a..5352ce50a97e309b5bf8cdd2059378b17a8f14ec 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 399669f7eba8e9569830e1c35b7f37c3c712025b..472dd462a40ca91ec62a773cf8fde19a25c72994 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 3a486f8262249b1be38a01461d2329732bde11ab..b56f3224b161b3f01f181bba97fd57e7eb04773d 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 b5dcd1d83c7fada652b79576738d9542f0638d67..7c2fe50fd76ddcec0fccd157f989def9a8daac9c 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 322ca8860f548cf8c0fa700e1a2755127659d2ce..9b8916fd00a2a14890b23109479af28afb14f6b1 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 08a233e97a01974850ddeac7b7ccd6b782ea897b..ba749f579714cbe02f502b02402b8467aff41c50 100644 (file)
@@ -7328,7 +7328,14 @@ static int detach_tasks(struct lb_env *env)
                            load < 16 && !env->sd->nr_balance_failed)
                                goto next;
 
-                       if (load/2 > env->imbalance)
+                       /*
+                        * Make sure that we don't migrate too much load.
+                        * Nevertheless, let relax the constraint if
+                        * scheduler fails to find a good waiting task to
+                        * migrate.
+                        */
+                       if (load/2 > env->imbalance &&
+                           env->sd->nr_balance_failed <= env->sd->cache_nice_tries)
                                goto next;
 
                        env->imbalance -= load;
@@ -8417,6 +8424,10 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
        if (!idlest)
                return NULL;
 
+       /* The local group has been skipped because of CPU affinity */
+       if (!local)
+               return idlest;
+
        /*
         * If the local group is idler than the selected idlest group
         * don't try and push the task.
index 517e3719027e619e5c7b565d1de9294dfffb5a3c..ce8f6748678a24b51e390fc9210b776579fa4b7a 100644 (file)
@@ -185,7 +185,8 @@ static void group_init(struct psi_group *group)
 
        for_each_possible_cpu(cpu)
                seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq);
-       group->avg_next_update = sched_clock() + psi_period;
+       group->avg_last_update = sched_clock();
+       group->avg_next_update = group->avg_last_update + psi_period;
        INIT_DELAYED_WORK(&group->avgs_work, psi_avgs_work);
        mutex_init(&group->avgs_lock);
        /* Init trigger-related members */
@@ -481,7 +482,7 @@ static u64 window_update(struct psi_window *win, u64 now, u64 value)
                u32 remaining;
 
                remaining = win->size - elapsed;
-               growth += div_u64(win->prev_growth * remaining, win->size);
+               growth += div64_u64(win->prev_growth * remaining, win->size);
        }
 
        return growth;
index 67e0c462b059cb3fcf036ccf2d7962c2b61290e8..a2659735db73b99623e1a53d0b2a1f11843c4577 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 74439ab5c2b660cb05302176cd56ee8489579749..ac99a3500076ab9f8de3609f3ab8aeff4b19c344 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 4bf050fcfe3be6deed57d1c7687d8985f4c71c56..3f655371eaf6ba4fe7d87b6cb10f39fb35192f9f 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 23459d53d57698b150e206a66ebd49beb8b44beb..ddb7e7f5fe8d8316b73f1c163bd7a3c894735e5a 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;
        }
@@ -4685,6 +4685,10 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
 
 int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
 {
+       if ((mask == TRACE_ITER_RECORD_TGID) ||
+           (mask == TRACE_ITER_RECORD_CMD))
+               lockdep_assert_held(&event_mutex);
+
        /* do nothing if flag is already set */
        if (!!(tr->trace_flags & mask) == !!enabled)
                return 0;
@@ -4752,6 +4756,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
 
        cmp += len;
 
+       mutex_lock(&event_mutex);
        mutex_lock(&trace_types_lock);
 
        ret = match_string(trace_options, -1, cmp);
@@ -4762,6 +4767,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
                ret = set_tracer_flag(tr, 1 << ret, !neg);
 
        mutex_unlock(&trace_types_lock);
+       mutex_unlock(&event_mutex);
 
        /*
         * If the first trailing whitespace is replaced with '\0' by strstrip,
@@ -8076,9 +8082,11 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
        if (val != 0 && val != 1)
                return -EINVAL;
 
+       mutex_lock(&event_mutex);
        mutex_lock(&trace_types_lock);
        ret = set_tracer_flag(tr, 1 << index, val);
        mutex_unlock(&trace_types_lock);
+       mutex_unlock(&event_mutex);
 
        if (ret < 0)
                return ret;
@@ -8796,7 +8804,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 +9252,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 c6de3cebc127fe83842887a300cae6d44dcd8c98..a5b614cc3887953946922742a0883819602a9e12 100644 (file)
@@ -320,7 +320,8 @@ void trace_event_enable_cmd_record(bool enable)
        struct trace_event_file *file;
        struct trace_array *tr;
 
-       mutex_lock(&event_mutex);
+       lockdep_assert_held(&event_mutex);
+
        do_for_each_event_file(tr, file) {
 
                if (!(file->flags & EVENT_FILE_FL_ENABLED))
@@ -334,7 +335,6 @@ void trace_event_enable_cmd_record(bool enable)
                        clear_bit(EVENT_FILE_FL_RECORDED_CMD_BIT, &file->flags);
                }
        } while_for_each_event_file();
-       mutex_unlock(&event_mutex);
 }
 
 void trace_event_enable_tgid_record(bool enable)
@@ -342,7 +342,8 @@ void trace_event_enable_tgid_record(bool enable)
        struct trace_event_file *file;
        struct trace_array *tr;
 
-       mutex_lock(&event_mutex);
+       lockdep_assert_held(&event_mutex);
+
        do_for_each_event_file(tr, file) {
                if (!(file->flags & EVENT_FILE_FL_ENABLED))
                        continue;
@@ -356,7 +357,6 @@ void trace_event_enable_tgid_record(bool enable)
                                  &file->flags);
                }
        } while_for_each_event_file();
-       mutex_unlock(&event_mutex);
 }
 
 static int __ftrace_event_enable_disable(struct trace_event_file *file,
index c9a74f82b14a279c270268c43cad6287d691d438..bf44f6bbd0c36c896f7110840043f9bd2befc1fd 100644 (file)
@@ -1662,7 +1662,7 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
        parse_error(pe, FILT_ERR_BAD_SUBSYS_FILTER, 0);
        return -EINVAL;
  fail_mem:
-       kfree(filter);
+       __free_filter(filter);
        /* If any call succeeded, we still need to sync */
        if (!fail)
                tracepoint_synchronize_unregister();
index f49d1a36d3ae3896672e0b1a65dad6648ac95f7d..f62de5f43e79dfd97a4e94bd38a502d2ca224ac7 100644 (file)
@@ -911,7 +911,26 @@ static notrace void trace_event_raw_event_synth(void *__data,
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       entry->fields[n_u64] = var_ref_vals[var_ref_idx + i];
+                       struct synth_field *field = event->fields[i];
+                       u64 val = var_ref_vals[var_ref_idx + i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
index d43710718ee592a660ef679f48a75c0ffe4ecd81..d45079ee62f8d9a75e53c616dd8b498d9ecbdd11 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 9a1c22310323d0a4bcf97f75a49d7cdfc859c7fe..9e31bfc818ff821dae0f82e4f5c1048a149a9f20 100644 (file)
@@ -148,8 +148,8 @@ static int tracing_map_cmp_atomic64(void *val_a, void *val_b)
 #define DEFINE_TRACING_MAP_CMP_FN(type)                                        \
 static int tracing_map_cmp_##type(void *val_a, void *val_b)            \
 {                                                                      \
-       type a = *(type *)val_a;                                        \
-       type b = *(type *)val_b;                                        \
+       type a = (type)(*(u64 *)val_a);                                 \
+       type b = (type)(*(u64 *)val_b);                                 \
                                                                        \
        return (a > b) ? 1 : ((a < b) ? -1 : 0);                        \
 }
index bc88fd939f4e72c43de15ad96c42aa2fdce4a996..cfc923558e04de32f603525343d9548128ca25cd 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 d1842fe756d554c6a6a74bf4727bcf31c16e7b7a..5ffe144c97945d7cd2bc1480b1ecbdd5a5b301da 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 c6aa03631df86d7837ea56d28d6059799803ef5b..0809805a7e231809387902b825fb2d89e7c43bd0 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 2fa710bb6358a7d8bf2ed483c3adf324b8386e55..c15d8ae68c9673b2fd62b0a7b7eab2aa387aec2e 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 606da187d1de904c226d3d53f56d696ab3d8964a..45442d9a4f525f271e00f395f02f059b25741d72 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,15 +2156,41 @@ 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
index 4d3b3d60d8939b65f65bfcaad9c4d4c497f83a7a..e9681dc4aa754ee5745e1f0f7c90913557ada172 100644 (file)
@@ -1061,6 +1061,26 @@ __alloc_vmap_area(unsigned long size, unsigned long align,
        return nva_start_addr;
 }
 
+/*
+ * 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:
@@ -1185,26 +1213,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
  */
@@ -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 74e8edce83ca4f148142cbec62e1b0d4f3026a13..572fb17c62733b2cca817953f0b45212abb5bebb 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 2cfdfbfbb2edbddd4d441539e468c2ca0fd0d8f3..bea6e43d45a0ddb5356ab369acec71e4b93bc188 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 4a89177def647db602edb96634f45cf1cfbcfd5f..4811ec65bc434d012c76bf0e55fb1ec2fec574a1 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 915c2d6f7fb9dad0790233d4c0268dc3cb07bf9f..f79205d4444f5fccf9244f4619c33709ee7cd464 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 8a8f9e5f264f2a70b246094fa7c31f1be8c0deef..b6fe30e3768f8a6d212cd1a3e92f63cf582a47a7 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 2c277b8aba38bf348093967a0fe7dd1d0aca4796..0ad39c87b7fd20e199af9f4b49d5f9598dcef222 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 d914257763b5d97ac63e61f84ddf8317018f7f61..28b3c258188c02baa4a2a3caec1dfd5d8a29c68c 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,
@@ -5590,8 +5590,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)); \
@@ -5599,9 +5599,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),                         \
@@ -5616,7 +5616,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));
@@ -5781,8 +5781,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)); \
@@ -7345,7 +7345,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));
@@ -7364,7 +7364,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);
@@ -7435,7 +7435,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,
@@ -7446,7 +7446,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,
@@ -7457,7 +7457,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),
@@ -7471,7 +7471,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;
@@ -7491,7 +7491,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;
@@ -7510,7 +7510,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,
@@ -7525,7 +7525,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,
@@ -7536,7 +7536,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,
@@ -7574,7 +7574,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);
@@ -7604,7 +7604,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,
@@ -7615,7 +7615,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,
@@ -7626,7 +7626,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,
@@ -7642,7 +7642,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;
@@ -7669,7 +7669,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;
@@ -7678,7 +7678,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;
@@ -7692,7 +7692,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
@@ -7709,7 +7709,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
@@ -7723,7 +7723,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;
@@ -7733,7 +7733,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;
@@ -7743,7 +7743,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;
@@ -7838,7 +7838,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)
@@ -7869,7 +7869,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,            \
@@ -7931,8 +7931,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);
@@ -7998,8 +7998,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),                 \
@@ -8032,8 +8032,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)                 \
@@ -8074,12 +8074,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);
@@ -8092,7 +8092,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),
@@ -8103,7 +8103,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),
@@ -8114,7 +8114,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(
@@ -8129,7 +8129,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;
@@ -8150,7 +8150,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;
@@ -8169,7 +8169,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),
@@ -8183,7 +8183,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),
@@ -8203,7 +8203,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),
@@ -8214,7 +8214,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));
@@ -8225,7 +8225,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):
@@ -8367,7 +8367,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),
@@ -8378,7 +8378,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),
@@ -8389,7 +8389,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(
@@ -8404,7 +8404,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;
@@ -8425,7 +8425,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;
@@ -8444,7 +8444,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),
@@ -8458,7 +8458,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),
@@ -8848,7 +8848,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):
@@ -8866,7 +8866,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 d524a693e00faa4e37572984fb4db357b9a0879a..2dbbb030fbedfa65698b2fa19cbd8c7c57f639ac 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 7c8390ad4dc613bf67b4845c37a7ed97360dd2a7..8310714c47fd7af0877dcf531ad46d0d2fef2903 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 a52e8ba1ced046b178fa069b1e0d690c537c6bc0..4af8a98fe7846bcb508352a0bd1947f8b8998cb5 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 572b6307a2dff1a29c6686fb963aeb4a51410447..8274f98c511cc0ca0cfe721f46941680aa9c7378 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 cfb0256067936839888b9c910997ff1a784021d1..9b153c7fcbb4d8ecd786bbe2349258eeebd8e693 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 716938313a32534f312c6b90f66ff7870177b4a5..d885ba868822a32b55c4dcf730b5e57282373792 100644 (file)
@@ -3947,7 +3947,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 923034c52ce40d85c91a54d1b107e2088d31bb85..9d0965252ddf723a0f4e64b8f4ef18675bdd55a3 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 ebb62a4ebe30d3bd6347f72711b23655cddc00c5..c4bdcbc84b07f0fd8516ccc46416aa801e4b6dfa 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 a8caf7386fa9cfd06e36657f702ac2cae9175f74..273f3838318b0e2612a89a28d9b2b48a23602ce5 100644 (file)
@@ -7603,7 +7603,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;
@@ -7651,7 +7651,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 7525063c25f5f998ee26bd1a8289670dc258ab9c..de3a9596b7f1bca045b8683bc48f66230fb65e75 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 46ca8bcca1bd5c31f900b4d89f11ee55b27098d9..faea72c2df328f6f691e1027a28a532364a5ea1e 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 39dc94f2491e305f9ef8bdbb91b320dca0b52017..bc9fd98c5d6d9db92e0d982dce6f93ceb893224a 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 c3c93e95b46e78c7f8d32673b86b1b862a0d4167..8b44a4de53294f25f85eb84bd3d5d4aac568d109 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 43eeb1f609f135ab7db6033e067c032b48c8a49a..5b779171565c1b2eb441ff1420cc31a97398beab 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 f92a82c73880807bfa1be1d65b483049b2378b3c..4c33dfc9dab5058333366b90c730a43cddd5d32c 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 2236455b10a3671b25547f048c26863fd651a70a..37253d399c6b8dd3ef1da16ab2ed78fd5567e2c6 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 90b2ab9dd449555260b2578d73539b2712a4a1f4..4e31721e729360c8bf555186ab6d4aa67cb00280 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 1047e8043084fdacb53b685027ea23e0697716aa..e3a37d22539c061ef946e648a44911a5edf4d42d 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 fd8ed766bdd17100ef8076af653905e9a8e3ae31..758a8c77f7361110268a756c001abe7dfbfa406f 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 d72ddb67bb742a0f6db6db765dd0035c94f636e8..9d3c4d2d893ab2372af651704efdc512494733a2 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 bf2d69335d4b963e254da4c1c93b6706438eb8d4..f685c0d737086d5a0317f87cbfeb890e2f4f2a9b 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 6c68971d99df702d79d651f38b6b5c1257c332e9..0d125de54285058591dcff0a6b400690a94679af 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 4d38d49d6ad91508d4d6cccbc79318c6a5f3f73e..50623218747f067c0ecf33a51d8d6b61e39ce139 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 7cfdce10de36b70104229e122d76aea272d80a05..774babbee045ff2649a078d212487c92c0932c1a 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 7affc3b50b61dd5d293e7b62cfe5675d0a632825..cfc1595802632c252241f5d6001d05c37a758268 100644 (file)
@@ -36,6 +36,7 @@ static int __init trace_printk_init(void)
 
        /* Kick off printing in irq context */
        irq_work_queue(&irqwork);
+       irq_work_sync(&irqwork);
 
        trace_printk("This is a %s that will use trace_bprintk()\n",
                     "static string");
index 7cbe6e72e363b79e8d464c68a73f4892a8382feb..a63380c6b0d20f8f2fd9c73b715343177f607bb7 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 fb55f262f42d6cee3f14475637b29d44028df97c..94153732ec00188b03968781ce908792c5ed7f5c 100644 (file)
@@ -310,6 +310,15 @@ static void output_label(const char *label)
        printf("%s:\n", label);
 }
 
+/* Provide proper symbols relocatability by their '_text' relativeness. */
+static void output_address(unsigned long long addr)
+{
+       if (_text <= addr)
+               printf("\tPTR\t_text + %#llx\n", addr - _text);
+       else
+               printf("\tPTR\t_text - %#llx\n", _text - addr);
+}
+
 /* uncompress a compressed symbol. When this function is called, the best table
  * might still be compressed itself, so the function needs to be recursive */
 static int expand_symbol(const unsigned char *data, int len, char *result)
@@ -360,19 +369,6 @@ static void write_src(void)
 
        printf("\t.section .rodata, \"a\"\n");
 
-       /* Provide proper symbols relocatability by their relativeness
-        * to a fixed anchor point in the runtime image, either '_text'
-        * for absolute address tables, in which case the linker will
-        * emit the final addresses at build time. Otherwise, use the
-        * offset relative to the lowest value encountered of all relative
-        * symbols, and emit non-relocatable fixed offsets that will be fixed
-        * up at runtime.
-        *
-        * The symbol names cannot be used to construct normal symbol
-        * references as the list of symbols contains symbols that are
-        * declared static and are private to their .o files.  This prevents
-        * .tmp_kallsyms.o or any other object from referencing them.
-        */
        if (!base_relative)
                output_label("kallsyms_addresses");
        else
@@ -380,6 +376,13 @@ static void write_src(void)
 
        for (i = 0; i < table_cnt; i++) {
                if (base_relative) {
+                       /*
+                        * Use the offset relative to the lowest value
+                        * encountered of all relative symbols, and emit
+                        * non-relocatable fixed offsets that will be fixed
+                        * up at runtime.
+                        */
+
                        long long offset;
                        int overflow;
 
@@ -402,12 +405,7 @@ static void write_src(void)
                        }
                        printf("\t.long\t%#x\n", (int)offset);
                } else if (!symbol_absolute(&table[i])) {
-                       if (_text <= table[i].addr)
-                               printf("\tPTR\t_text + %#llx\n",
-                                       table[i].addr - _text);
-                       else
-                               printf("\tPTR\t_text - %#llx\n",
-                                       _text - table[i].addr);
+                       output_address(table[i].addr);
                } else {
                        printf("\tPTR\t%#llx\n", table[i].addr);
                }
@@ -416,7 +414,7 @@ static void write_src(void)
 
        if (base_relative) {
                output_label("kallsyms_relative_base");
-               printf("\tPTR\t_text - %#llx\n", _text - relative_base);
+               output_address(relative_base);
                printf("\n");
        }
 
index 77ffff3a053ccb844a0f368ae59661a01bc8444c..9f1de58e9f0c995fba0a0a0cf076be4a18e79ca1 100644 (file)
@@ -254,6 +254,13 @@ static int expr_eq(struct expr *e1, struct expr *e2)
 {
        int res, old_count;
 
+       /*
+        * A NULL expr is taken to be yes, but there's also a different way to
+        * represent yes. expr_is_yes() checks for either representation.
+        */
+       if (!e1 || !e2)
+               return expr_is_yes(e1) && expr_is_yes(e2);
+
        if (e1->type != e2->type)
                return 0;
        switch (e1->type) {
index d1d757c6edf4f63bdf66ef9bb4d9bf0f2601d0aa..3a5a4b210c8688f4ddcede7196a2e753d8bf05ed 100755 (executable)
@@ -55,12 +55,10 @@ CONFIG_FLAGS=""
 if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
 if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
 if [ -n "$PREEMPT_RT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT_RT"; fi
-UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
 
 # Truncate to maximum length
-
 UTS_LEN=64
-UTS_TRUNCATE="cut -b -$UTS_LEN"
+UTS_VERSION="$(echo $UTS_VERSION $CONFIG_FLAGS $TIMESTAMP | cut -b -$UTS_LEN)"
 
 # Generate a temporary compile.h
 
@@ -69,10 +67,10 @@ UTS_TRUNCATE="cut -b -$UTS_LEN"
 
   echo \#define UTS_MACHINE \"$ARCH\"
 
-  echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
+  echo \#define UTS_VERSION \"$UTS_VERSION\"
 
-  echo \#define LINUX_COMPILE_BY \"`echo $LINUX_COMPILE_BY | $UTS_TRUNCATE`\"
-  echo \#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
+  printf '#define LINUX_COMPILE_BY "%s"\n' "$LINUX_COMPILE_BY"
+  echo \#define LINUX_COMPILE_HOST \"$LINUX_COMPILE_HOST\"
 
   echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | grep ' version ' | sed 's/[[:space:]]*$//'`\"
 } > .tmpcompile
index e0750b70453f2e19e14175b176dc3cb7110844c1..7c230016b08d155bf2abb906f2227a0586154e6c 100755 (executable)
@@ -174,7 +174,7 @@ Source: $sourcename
 Section: kernel
 Priority: optional
 Maintainer: $maintainer
-Build-Depends: bc, kmod, cpio, bison, flex | flex:native $extra_build_depends
+Build-Depends: bc, rsync, kmod, cpio, bison, flex | flex:native $extra_build_depends
 Homepage: http://www.kernel.org/
 
 Package: $packagename
index f19a895ad7cdf6c9bf24e05ffc6ee394ab3363ab..ef8dfd47c7e391328e2b1e7886b74c1ea87a231b 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 dd313438fecf9763eb5179f966620aaaef5d4ccc..47c041563d41c5fe16e71d70f7e001f48ff1b846 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 074f27538f55968e1a3ee3d2187d89bfb99d8f44..5f40807f05b3d1d27cc21d875302af37959ef758 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 9bcc404131aa0d30c86045d2b24a03856e939398..b975f8f11124b7f79112a3bced90673c9f5d7f5a 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 c039373488bd940d2a1c6dac919e46e586cd3002..ba3e2da14ceff60636d688cb1e4f78a7cb62b210 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 a9810ac2776f6c2fb75e598945b7dbace69f5d14..08ec7f48f01d09d643f2f0b69021686a88adad7e 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 1fe581167b7b9aad19be6a06c3c5d98d3183cf45..d083225344a06d7a5aadb5b9afb5d7918f459c02 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 4e3bd9a2bec0656c7337817c9af71bd93fba7a98..bd91c6ecb1123bf755b7952d3ffc0e3f50943738 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 349b4d09e84f6f885dd3a9bff2b0e29b127795e8..0059709310303c07a11bce1c04a551ac6502cdce 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 9124603edabe58690d90562f0aa00d9413909d84..67fd3e844dd6aca2a1a0e4045e8d35f749a8b0fc 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 f9707fb05efe6812e9ec2ad69fb45e96b9bd9db5..682ed39f79b015a3982b6e149ff3bf1c0d3632b6 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 50d4a87a6bb34b57ead7cee72a5e2ceb0924b74f..f02f5b1568dee6f5e083e11417f9b67e7d355073 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 2f3b7a35f2d9cdb3b9262d220c962336f6653205..ba56b59b3e17857747c533d2635e9b61e468a528 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 35b4526f0d287a582da079a9af63f9db070e3fab..b856b89378ac556d1dead5ec23b875542ac6d736 100644 (file)
@@ -1419,7 +1419,6 @@ static bool atpx_present(void)
                                return true;
                        }
                }
-               pci_dev_put(pdev);
        }
        return false;
 }
index b7a1abb3e2318ecc1051e6b8bbef49ea6fa46f73..32ed46464af7ad0a3ec1197cb935db3a1571317f 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 78647ee02339fbe36d1374dbf7fbbec946b458f0..630b1f5c276d4eb348e65603ffbcd1e6e087660b 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 6d6e34b3b3aa5c091f52248d5b79d07d084f8ecf..dbfafee97931a42952dd33690bc4f80209e39cde 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 f4ee6798154af52377c7a6949e8fc99a2b0134fe..7a5621e5e2330dd872e3835811862c9b339dbfd8 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 f8b5b960e5970ef3182aaa14b528f09fab6f50be..4eaa2b5b20a58b41ff075e9977acaeba4644ad0f 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 f6bf4cfbea23fa0aae7e5af9ec933870597fb278..e46b6ada13b1b01af12a8a775cc4fcc8d6e95ef6 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 57965cd678b4e5ae7de6865dacd7ff4c8eee793a..a197114b0dad3fc648952b8f272fb8b87c1a77c1 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 3af36ec928e93480ba4332430364917d926f5bd7..088b779317276f266ed4cd59571dbb8245a6d35f 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 b1713fffa3eb925f3d79f6d23b2c2bbb2bd38ddd..ae6f6121bc1b0ffadef6f57828b46b0fe89da958 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 7d7ea15d73e0a677c61b094fe1e91b592378a7f7..5ffbaddd6e499579ef98d3c35b146ab645fc2c4b 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 3e5c69fbc33ad752afa07868d0df00444aeb920d..d9d59f45833fdd2f02a3f202b80941535e39f1ca 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 10b82bf043d1ab190e50895c67907c30b8cf6457..55e9f8800b3e103638e38b651aa9e37ac37fdcc7 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 fbecbb74350b51de1583b2be7bec5408fef46b7b..68bcec5241f74fb6da8345f722b1ed7a43f6decf 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 dd2b5ad08659107f41184234086eb81b10608554..243f683bc02a7361fb89ff2eaa7ab1f6e1ab751c 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 5d08ae0667380bea84b98537cb4d2c66c3a76281..fb9ba881970604331a6d825f09893609eae9ada2 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 61f230324164d0a6765aaba8b55df82982b38263..6615ef64c7f55ad1c7bd94f186babaa64feab966 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 062653ab03a37b1cac41e11f1a5984805b8ca688..1c84ff1a5bf96b09e303ec08d5d4c6e1e565aad9 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 76b7ee637e869780dce61b0f887309692a08849d..01e7bc03d92f96e9e6b9fc0a16453cd48fdfb8b7 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 81d2af000a5c80b2e7f7c36a31029414d32d95c3..b28613149b0cce2e4a2b1623091fac095808818b 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 2abf80b3eb52fee2c0e7f06c9c6e051028f2104d..92ef6a796fd5ec8dd554a53d76d9da306c48792e 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 9a9a381a908dee467665c979fecc7d31fb58e3bc..432d12bd493791837ff38f8afe0e71c35d858915 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 d82ab981e8408ad0f9ea0d9179eff846976a7284..e20b806ec80f1aa1cb74989baca3130c8ff04427 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 2769360f195cafe1ead78ea917495778a7a52c21..03cd7c19a683bb809ab7ad78e9e4916d7a2113ac 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 67c21f9bdbad2556be4114dfa09b8006a11e708e..820e5751ada71ab1ce0e08b90e026d4a9231dd36 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 b0f72dea8b11ac689c990971dbf78c1601ef4e7a..264e266a85bf6a99c5b27b47733ad5f11b5e02d5 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 0652d3eed9bda96828657cba8250cdc9903a2469..e9b62498fe75a3f3fce3692678e5ff28bbb28880 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 20ce682a2540f389dc62f29dbf07c0b3f32620ea..084e98da04a7ec3e102c26c71fb2f0234437a844 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 92748660ba51234f31a651d9181f50605418f0c9..df767afc690fea3c0eb66e0135f7437e37953e3a 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 f8f3dc0a6690e92f19ce5bc398f33451907a66cb..fd5d25a474b7c66a04955623f042c3bfb43f62cb 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 8a5b2f8f8eb98b0f1f170960239327d420971354..868bf7996c0f8920e589b58b192528c5a602a9fe 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 469dc512cca3513f0a38400c5ed1598096147de9..5400d7e057f143abdeb124c229ccfe7cdeb58196 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,9 +1953,24 @@ 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
  */
@@ -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 39ccfe9311c387ba0f6c0f88e605c05b0189e02a..1beb174ad9505634151c5ac2896ae63bcced028e 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 52641d8ca9e83f25b983f3cc6be115c37bad2d98..f0a16b4adbbd63c421006f6ca9b0fd9a892f7a5d 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 99335e1f4a275b1dbc86219a6dee7701b18fd624..4a02178324641f555336164316ba2e30805c3719 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 7b35e98d3c58b1df9f4315e3f76a2564c25a106b..ad80a5c885d598231ccf207ac48d2d908eaf1b85 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 cbb429f550625a645650786b63b3cddc6c8ad6d0..c874c017c636969ef8b430213e89e78d18f9732c 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 f440989fa55e443d9355659ec6f08c09c8c501b3..349bb81482abbccf099ae803ba8fe16e0e97b358 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 6a5bb2b170391da59b572f8c4230209fb04199e2..cf95baef7b61c1d2c116365d3135dd951fa43fad 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 6e2495cc4517191656784a9bf61a43653901e7cc..4284307d78226f2f76fa6673c6d22339ccca5bc0 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 07042511dca925fc3cbf3ce9594476bce0d19b47..d49de40b6818021d1ba8a75522c4cbf2901fff76 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 bbe5a0d16e51083d5432c30f6a45dc8fcec7211f..80f14f52e3f6072fcc1ca179e544a2b945fac5e5 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 9664a72a089daf4d4551a83227b1f63fa1fe22b8..7e124a7b8bfdc4e42ba48846caeab4f66a46c41e 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 b5063d3b6fd077fd8b5b4d35936f44cd6609bae7..fb19ef63cc35fa78ad1a7a2318031ff70a770fe0 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 830d563de8898f92559af9dd5bcf5803f948cefa..387311c6726407eed80ccd4dc013e1fb9a330338 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 0a15253b438c5e413bfc01159fcb627f6c329650..a098c2ebf4eac474c69b554ac40a279fbfc8afa7 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 dc80044bc46f48cdd7123eced665a33017bd6343..795e353de095094ae482057cafcb9d8a1f0ee984 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 a1dc1672435201513b3e3ad3a7bbbab59b4a32ec..68039a96c1dcaa7a2b9c5f54882ce39b98c71b0e 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 2ca1fafa620dfca8ee992b87eb35fe5c36220d0f..f93f4e703e4c76e44a0341ca1273646fd53ece7d 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 205ddbb80bc1fab0745406438add906e57671519..ae9e65aa249180cb30391edc802d37df3e238fb8 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 5a89857b0381ce23aaceb9ddd2f44647b8bfb2af..4dc06289f4c75334619705ffa19bef32f6ebb504 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 a2fbccf1922f2894e8380234c740afe0952dfd20..74dc8c3f0b667f06f6f6c71d53b05b96e7ac11f1 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 ac9aa497f84ab3151799e1bc4689b5e0b0fd1dc4..6a17ad730cbc112b7e3e5938a4cc47b688d09440 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 557f5815a9c968b21ed3c53e89cde7ccee435555..c82ec39a4ad064dc349fc65ce6feb7553442605b 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 436ce33f1182e7d1721e760016f3b21c442df4ba..5da8296b667e753a032d9c7eed7fd974f1ea7a9b 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 68618152ea2c62578368767fa1ddfd550b076015..89e070727e1bd388bc057d99c4a998c7dc6a701d 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 bc7151d639d7ee7f7a7997b7edbeb2ae9738eea9..45a34ce4fe89f6d7250bc3eca62ab09a72edad9d 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 49c5f123d81154283b7a998ac73453af676352b1..961fe4395758e0f0893e55d03cd0826765b04419 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 113d19e9267840aeaf6dd0995461efedc710de3b..746734ce09be7fc32717fa3a0205a85e3b811e75 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 2ba32af9bc366a2cf72bb568989c8d253b541726..f94653229dd46ee26127ad1f0d6e2e840b68d810 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 c80f16fde6d0ee9248935cfc59d605f0a7717a37..5402cd3120f9d1a1f44e25f721941536e667a40c 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 e501729c3dd117d0a86d2606a487914a38fff429..832f3cb40b34f23cc82279025aef98c733dec7a2 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 e2446966b65137cf32d80a65ff3765fee73da0ad..d69b2a8fc0bc7fb601968c86b3b038f78d074dc1 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 9294769dec64e9880283307f59bfbae40353cc1e..5f465fd81315d90a8b6684cd2006f56c37836b7a 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 603ff9c2e9a17295ea6868cc3575313ee90a51b8..3e909b30600351b25fa90acccf1b19f957f8cdd0 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 c6b485b3a2cbad74eeea7cbf8611cfe954129abb..50c053235752042bd68adf7595bb948c46cf1634 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 0ca539bb60f62b631faafbb6d897873d29c70247..e7feb60f9fa995b3179a51581e810fd3697a4137 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 047d7e11aa6f83aef22c5e54a13fbe46cf9e7375..21d7a0c2c2e83c76500f8189e94671b21334ce16 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 a3c595fba9434df3e1269b5f1cd5148ba04f88db..1692529639b0df28324735498dcac49a51891e63 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 7115aa32a51ee4b0ee4d2a270eeae5420fe277be..5f05db75cdd866be44b0702b440369df93cb6a68 100644 (file)
@@ -259,6 +259,11 @@ static struct test generic_tests[] = {
                .desc = "Print cpu map",
                .func = test__cpu_map_print,
        },
+       {
+               .desc = "Merge cpu map",
+               .func = test__cpu_map_merge,
+       },
+
        {
                .desc = "Probe SDT events",
                .func = test__sdt_event,
@@ -296,6 +301,10 @@ static struct test generic_tests[] = {
                .desc = "time utils",
                .func = test__time_utils,
        },
+       {
+               .desc = "Test jit_write_elf",
+               .func = test__jit_write_elf,
+       },
        {
                .desc = "maps__merge_in",
                .func = test__maps__merge_in,
index 8a0d236202b05ba179199b2709080b949c5d52d3..4ac56741ac5fe6375fb4e0a1171b7bbd5a7f7c42 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 1ee8704e22849726dd30a0aa74642515fd07f059..1e8a9f5c356dd623226c5fb7dee5e4f30b002b6f 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 25aea387e2bf0ed13afde728df4ad906556557a8..9a160fef47c9c91d032b00701413e9521dae25ea 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 1a8d3be2030e97220a698e8a1f8d99db55570240..062ca849c8fda9c0d032c154c380ddf067a34a26 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 57943f3685f8c84226a0cd970e9cbb448d8766e5..3a442f0214684cd85e4591e55aad713839a1947d 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 fdce590d22786ae21d65494fc67a3dc5a4ecb60b..1548237b6558d9105dcc07ae8094fb7f06dcc2b4 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 3655b9ebb1473fccd594276f093603f9998b06f4..f5bd5c386df1138423313860c34ab331d34024a4 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 f4dea055b0808941229374cf6a93d7992888b406..a69e64236120a7d4c8bf4ceb84434a439b51f6ac 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 ddc5ee6f6592bed23532aff20f75c7a76db53361..dc14f4a823cd6a1cee5e2f9edae77cb2ac2e92bb 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 f9f18b8b1df9a2e3973aadb6938cb2c20c025b79..aed49806a09bab8f9a835fc965bca33fec796c2c 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 becc2d1094237580901dfe0578ad63900cc77635..93ad27830e2bdf7fa2758c53c98b3a95ba167de9 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 f01d48a8d707987de71244cec8df09353c592129..b8a5159361b4123651509d9510e851a51f6c1a42 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 416d174d223c522e7690e3efd4eec74bb7576440..c8c5410315e817c2b9533eb8df718dc1bf98915f 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 6a4d350d5cdbab9f0fbabe8ac8bc53f3cefbc6fc..02aee946b6c14c1819eebf329e9536c43f9edc51 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 345b5ccc90f68bfd353339988bae29a3f8f080b2..9fcba2872130b117c1b400826beb169cc8175e7e 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 332cb730785bd3defe9b8e29c8d6080c6551cd68..5f26137b8d6028fa0fc00e772ebacf43ba3e007e 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 bfa9aaf36ce6fc6027853bc6e6c90e4f2496bdc1..fb990efa54a8a83d8960aa0cedde11301f819ca2 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 4a12baa0cd4e0d6cd38b3a954a736ece3be32fc9..a2a8ea6beae34509aa7c08bb95ba71aef3b6c027 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 c4a9196d794c9d42251400122884a28b3ef9b492..6aca8d5be1593fa8e5283a34a9b59a54352b72e6 100644 (file)
@@ -5,6 +5,7 @@ ldflags-y += --wrap=devm_ioremap_nocache
 ldflags-y += --wrap=devm_memremap
 ldflags-y += --wrap=devm_memunmap
 ldflags-y += --wrap=ioremap_nocache
+ldflags-y += --wrap=ioremap
 ldflags-y += --wrap=iounmap
 ldflags-y += --wrap=memunmap
 ldflags-y += --wrap=__devm_request_region
index 3f55f2f99112fe5475a0d414e6f33e4d5d7dde87..6271ac757a4b2e9d11d91db5592639ca5d0679d6 100644 (file)
@@ -193,6 +193,12 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
 }
 EXPORT_SYMBOL(__wrap_ioremap_nocache);
 
+void __iomem *__wrap_ioremap(resource_size_t offset, unsigned long size)
+{
+       return __nfit_test_ioremap(offset, size, ioremap);
+}
+EXPORT_SYMBOL(__wrap_ioremap);
+
 void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size)
 {
        return __nfit_test_ioremap(offset, size, ioremap_wc);
index 36fb59f886ea81baef28a712c13f6d4ff204ac12..1a52f2883fe02cd5718903be31e7d6a03cc31639 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 86a1f07ef2ca70c672b4ea897340dfde4515d2f7..71fa3f49e35e20b7bf36baf74b06813e2d1336f6 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 86986c4bba549ad770d73b2990ee76f4ebf6a5e9..5d4550591ff9f789d0f783c891b3cd766ceee27d 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 5862eee91e1d9b474bb1b91b6c8628e87aa53817..6e3dbe5f96b7b76c6361f5e286c868e9c3e7edfa 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 1221240f8cf6ed2f5975b63a70b194aa965c617a..3f2aee115f6e22da3939ea425106e364a9efc42f 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 064a284e4e75905c4c4c8fbaaee81641c7330a86..c80007aa9f862e187da0dc1396025ed52c6a4e5c 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 18fff69fc433346f59e7ea3b3fe1d2ded727b605..f546c1b66a9b1d0b58bfa2a247a525d7e9647b25 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 18e1c7992d30d8e2ddf5841b792a72ab604c1e1b..fb4733faff12818ea06f36fde72d635490e8071f 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 ec7e48118183504758bcca0b19d71f34c6b5717f..31f7c2a0a8bd462da9329d6e90b7fae60ca66bc5 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 84de7bc74f2cf1f5272a8bd3b0f81ecd00a296a6..a8d20cbb711cf658ab93e4b8bfe97b04865d0845 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 98da7a5047375a16167120f950f895e4a07ef636..fa02c4d5ec13c1e1071f433c708d08265bbe581e 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 8f40c6ecdad188458d526af08f4bf4731d34c30c..0c4d50644c1311108f249fa0cdd3a8b425cb6fbd 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 80521d46220ccc0a33edb79f8f4dbd993f39ebd7..8155c2ea7ccbb6ed1b9685f3c602105eb2c26173 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 828c185846248031ff598670d393e34a38fa24df..d0fcb66a88a68a0bf9e57d5da24aadfd695c12f9 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 d4973be53493226b19dcca5e7140e997ea964e8b..728be7c69b764fe48592bd22e20d01a0fe19d68c 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()
index 4a753a48767b76659d7f9d60975121644fbca3dd..84598469e6ff35d6ffa3cbf87bfe46306f31dd43 100644 (file)
@@ -91,7 +91,7 @@ endif
 # asm-generic/*.h is used by asm/*.h, and should not be included directly
 header-test- += asm-generic/%
 
-extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h'))
+extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h' 2>/dev/null))
 
 quiet_cmd_hdrtest = HDRTEST $<
       cmd_hdrtest = \