OSDN Git Service

Merge tag 'block-5.6-2020-03-13' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Mar 2020 19:45:23 +0000 (12:45 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 13 Mar 2020 19:45:23 +0000 (12:45 -0700)
Pull block fixes from Jens Axboe:
 "A few fixes that should go into this release. This contains:

   - Fix for a corruption issue with the s390 dasd driver (Stefan)

   - Fixup/improvement for the flush insertion change that we had in
     this series (Ming)

   - Fix for the partition suppor for host aware zoned devices
     (Shin'ichiro)

   - Fix incorrect blk-iocost comparison (Tejun)

  The diffstat looks large, but that's a) mostly dasd, and b) the flush
  fix from Ming adds a big comment"

* tag 'block-5.6-2020-03-13' of git://git.kernel.dk/linux-block:
  block: Fix partition support for host aware zoned block devices
  blk-mq: insert flush request to the front of dispatch queue
  s390/dasd: fix data corruption for thin provisioned devices
  blk-iocost: fix incorrect vtime comparison in iocg_is_idle()

707 files changed:
.clang-format
CREDITS
Documentation/admin-guide/acpi/fan_performance_states.rst
Documentation/admin-guide/bootconfig.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/arm/arm,scmi.txt
Documentation/devicetree/bindings/arm/arm,scpi.txt
Documentation/devicetree/bindings/arm/bcm/brcm,bcm63138.txt
Documentation/devicetree/bindings/arm/cpus.yaml
Documentation/devicetree/bindings/arm/fsl.yaml
Documentation/devicetree/bindings/arm/hisilicon/hi3519-sysctrl.txt
Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
Documentation/devicetree/bindings/arm/omap/mpu.txt
Documentation/devicetree/bindings/arm/psci.yaml
Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml
Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-osc-clk.yaml
Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-gt-clk.yaml
Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tv-encoder.yaml
Documentation/devicetree/bindings/display/bridge/anx6345.yaml
Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml
Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml
Documentation/devicetree/bindings/display/simple-framebuffer.yaml
Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
Documentation/devicetree/bindings/dma/ti/k3-udma.yaml
Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml
Documentation/devicetree/bindings/gpu/arm,mali-midgard.yaml
Documentation/devicetree/bindings/iio/adc/samsung,exynos-adc.yaml
Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
Documentation/devicetree/bindings/leds/common.yaml
Documentation/devicetree/bindings/leds/register-bit-led.txt
Documentation/devicetree/bindings/media/ti,cal.yaml
Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
Documentation/devicetree/bindings/mfd/max77650.yaml
Documentation/devicetree/bindings/mfd/tps65910.txt
Documentation/devicetree/bindings/mfd/twl-family.txt [moved from Documentation/devicetree/bindings/mfd/twl-familly.txt with 100% similarity]
Documentation/devicetree/bindings/mfd/zii,rave-sp.txt
Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
Documentation/devicetree/bindings/mmc/mmc-controller.yaml
Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt
Documentation/devicetree/bindings/net/brcm,bcm7445-switch-v4.0.txt
Documentation/devicetree/bindings/net/fsl-fman.txt
Documentation/devicetree/bindings/nvmem/nvmem.yaml
Documentation/devicetree/bindings/phy/allwinner,sun4i-a10-usb-phy.yaml
Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml
Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
Documentation/devicetree/bindings/power/domain-idle-state.txt [deleted file]
Documentation/devicetree/bindings/power/domain-idle-state.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/power/power-domain.yaml
Documentation/devicetree/bindings/power/power_domain.txt
Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
Documentation/devicetree/bindings/regulator/regulator.yaml
Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml
Documentation/devicetree/bindings/reset/st,stm32mp1-rcc.txt
Documentation/devicetree/bindings/sound/st,stm32-sai.txt
Documentation/devicetree/bindings/sound/st,stm32-spdifrx.txt
Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
Documentation/devicetree/bindings/thermal/brcm,avs-ro-thermal.yaml
Documentation/devicetree/bindings/timer/allwinner,sun4i-a10-timer.yaml
Documentation/driver-api/dmaengine/client.rst
Documentation/filesystems/debugfs.txt
Documentation/filesystems/porting.rst
Documentation/hwmon/adm1177.rst
Documentation/kbuild/makefiles.rst
Documentation/networking/devlink/devlink-region.rst
Documentation/networking/net_failover.rst
Documentation/networking/phy.rst
Documentation/networking/rds.txt
Documentation/power/index.rst
Documentation/sphinx/parallel-wrapper.sh
Documentation/virt/kvm/api.rst
Documentation/x86/index.rst
MAINTAINERS
Makefile
arch/Kconfig
arch/arm/boot/dts/am437x-idk-evm.dts
arch/arm/boot/dts/bcm2711-rpi-4-b.dts
arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7-l4.dtsi
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra76x.dtsi
arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
arch/arm/boot/dts/imx7-colibri.dtsi
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/ls1021a.dtsi
arch/arm/boot/dts/motorola-mapphone-common.dtsi
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/configs/bcm2835_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/include/asm/kvm_host.h
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/common.h
arch/arm/mach-imx/resume-imx6.S [new file with mode: 0644]
arch/arm/mach-imx/suspend-imx6.S
arch/arm/mach-meson/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/io.c
arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/virt.h
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c
arch/arm64/mm/context.c
arch/mips/boot/dts/ingenic/ci20.dts
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/ingenic/jz4780.dtsi
arch/mips/boot/dts/ingenic/x1000.dtsi
arch/mips/include/asm/sync.h
arch/mips/kernel/setup.c
arch/mips/kernel/vpe.c
arch/mips/vdso/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/mm/mem.c
arch/riscv/Kconfig
arch/riscv/Kconfig.socs
arch/riscv/Makefile
arch/riscv/boot/.gitignore
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
arch/riscv/configs/defconfig
arch/riscv/configs/rv32_defconfig
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/syscall.h
arch/riscv/kernel/entry.S
arch/riscv/kernel/head.S
arch/riscv/kernel/module.c
arch/riscv/kernel/ptrace.c
arch/riscv/kernel/traps.c
arch/riscv/mm/init.c
arch/riscv/mm/kasan_init.c
arch/s390/include/asm/pgtable.h
arch/s390/pci/pci.c
arch/x86/Makefile
arch/x86/crypto/Makefile
arch/x86/include/asm/io_bitmap.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/vmx.h
arch/x86/include/asm/vmxfeatures.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/kvm.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process.c
arch/x86/kvm/Kconfig
arch/x86/kvm/Makefile
arch/x86/kvm/emulate.c
arch/x86/kvm/irq_comm.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmutrace.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/capabilities.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/nested.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/mm/dump_pagetables.c
arch/x86/platform/efi/efi_64.c
arch/x86/xen/enlighten_pv.c
drivers/acpi/acpi_watchdog.c
drivers/android/binder.c
drivers/android/binder_internal.h
drivers/android/binderfs.c
drivers/atm/nicstar.c
drivers/auxdisplay/Kconfig
drivers/auxdisplay/charlcd.c
drivers/auxdisplay/img-ascii-lcd.c
drivers/base/core.c
drivers/base/platform.c
drivers/base/swnode.c
drivers/block/floppy.c
drivers/block/paride/pcd.c
drivers/block/virtio_blk.c
drivers/block/xen-blkfront.c
drivers/bus/ti-sysc.c
drivers/cdrom/gdrom.c
drivers/char/ipmi/ipmi_si_platform.c
drivers/cpufreq/cpufreq.c
drivers/devfreq/devfreq.c
drivers/dma-buf/dma-buf.c
drivers/dma/coh901318.c
drivers/dma/idxd/cdev.c
drivers/dma/idxd/sysfs.c
drivers/dma/imx-sdma.c
drivers/dma/tegra20-apb-dma.c
drivers/dma/ti/k3-udma.c
drivers/edac/synopsys_edac.c
drivers/firmware/efi/efi.c
drivers/firmware/imx/imx-scu.c
drivers/firmware/imx/misc.c
drivers/firmware/imx/scu-pd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/renoir_ppt.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/smu_v12_0.c
drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_dma.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/exynos/exynos_drm_scaler.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/intel_psr.h
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
drivers/gpu/drm/i915/gt/intel_gt_requests.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_timeline.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/opregion.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_perf_types.h
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_request.h
drivers/gpu/drm/i915/i915_utils.h
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_mixer.h
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/hid/hid-alps.c
drivers/hid/hid-apple.c
drivers/hid/hid-bigbenff.c
drivers/hid/hid-core.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-ite.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/adt7462.c
drivers/hwmon/pmbus/xdpe12284.c
drivers/i2c/busses/i2c-altera.c
drivers/i2c/busses/i2c-jz4780.c
drivers/ide/ide-gd.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/rw.c
drivers/infiniband/core/security.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/qib/qib_verbs.c
drivers/infiniband/sw/siw/siw_main.c
drivers/interconnect/core.c
drivers/macintosh/therm_windtunnel.c
drivers/md/dm-bio-record.h
drivers/md/dm-cache-target.c
drivers/md/dm-integrity.c
drivers/md/dm-mpath.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-verity-target.c
drivers/md/dm-writecache.c
drivers/md/dm-zoned-target.c
drivers/md/dm.c
drivers/media/mc/mc-entity.c
drivers/media/platform/vicodec/codec-v4l2-fwht.c
drivers/media/usb/pulse8-cec/pulse8-cec.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/misc/altera-stapl/altera.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-omap.c
drivers/mmc/host/sdhci-pci-gli.c
drivers/mmc/host/sdhci-tegra.c
drivers/net/bonding/bond_alb.c
drivers/net/can/dev.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global2.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fman/Kconfig
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/freescale/fman/fman.h
drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
drivers/net/ethernet/huawei/hinic/hinic_main.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag.h
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/efx_channels.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/sfc/tx_common.c
drivers/net/ethernet/sfc/tx_common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/xilinx/ll_temac.h
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ipvlan/ipvlan_core.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/phy/bcm63xx.c
drivers/net/phy/marvell.c
drivers/net/phy/mscc.c
drivers/net/phy/phy-c45.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/slip/slhc.c
drivers/net/slip/slip.c
drivers/net/team/team.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/veth.c
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/mediatek/mt76/dma.c
drivers/of/of_mdio.c
drivers/pci/controller/pcie-brcmstb.c
drivers/perf/arm_pmu_acpi.c
drivers/perf/fsl_imx8_ddr_perf.c
drivers/phy/allwinner/phy-sun50i-usb3.c
drivers/phy/broadcom/phy-brcm-sata.c
drivers/phy/motorola/phy-mapphone-mdm6600.c
drivers/phy/phy-core.c
drivers/phy/ti/phy-gmii-sel.c
drivers/pinctrl/cirrus/pinctrl-madera-core.c
drivers/pinctrl/core.c
drivers/pinctrl/freescale/pinctrl-scu.c
drivers/pinctrl/meson/pinctrl-meson-gxl.c
drivers/pinctrl/pinctrl-falcon.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
drivers/platform/chrome/wilco_ec/properties.c
drivers/regulator/stm32-vrefbuf.c
drivers/reset/Kconfig
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/libfc/fc_disc.c
drivers/scsi/sd_zbc.c
drivers/scsi/sr.c
drivers/soc/imx/soc-imx-scu.c
drivers/spi/atmel-quadspi.c
drivers/spi/spi-bcm63xx-hsspi.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-qup.c
drivers/spi/spi-zynqmp-gqspi.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/media/hantro/hantro_drv.c
drivers/staging/speakup/selection.c
drivers/staging/wfx/Documentation/devicetree/bindings/net/wireless/siliabs,wfx.txt
drivers/tee/amdtee/Kconfig
drivers/tee/amdtee/core.c
drivers/tty/serdev/core.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/mvebu-uart.c
drivers/tty/vt/selection.c
drivers/tty/vt/vt.c
drivers/usb/cdns3/gadget.c
drivers/usb/core/hub.c
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/gadget.c
drivers/usb/misc/usb251xb.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/led_bl.c [new file with mode: 0644]
drivers/video/console/vgacon.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_ring.c
drivers/watchdog/wdat_wdt.c
drivers/xen/xen-pciback/pciback.h
drivers/xen/xenbus/xenbus_comms.c
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenbus/xenbus_probe_backend.c
drivers/xen/xenbus/xenbus_xs.c
fs/afs/addr_list.c
fs/afs/internal.h
fs/btrfs/inode.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb1ops.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/crypto/keysetup.c
fs/debugfs/file.c
fs/ext4/super.c
fs/fat/inode.c
fs/fcntl.c
fs/gfs2/inode.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/jbd2/transaction.c
fs/locks.c
fs/open.c
fs/zonefs/Kconfig
fs/zonefs/super.c
include/acpi/actypes.h
include/crypto/curve25519.h
include/drm/drm_dp_mst_helper.h
include/drm/drm_gem_shmem_helper.h
include/linux/bootconfig.h
include/linux/cgroup.h
include/linux/debugfs.h
include/linux/device.h
include/linux/hid.h
include/linux/icmpv6.h
include/linux/inet_diag.h
include/linux/kvm_host.h
include/linux/mm.h
include/linux/mmc/host.h
include/linux/netfilter/ipset/ip_set.h
include/linux/phy.h
include/linux/platform_data/spi-omap2-mcspi.h
include/linux/platform_device.h
include/linux/rhashtable.h
include/linux/workqueue.h
include/net/fib_rules.h
include/soc/mscc/ocelot_dev.h
include/sound/soc.h
include/uapi/linux/dm-ioctl.h
include/uapi/linux/in.h
include/xen/interface/io/tpmif.h
include/xen/xenbus.h
init/Kconfig
init/main.c
kernel/audit.c
kernel/auditfilter.c
kernel/cgroup/cgroup-v1.c
kernel/cgroup/cgroup.c
kernel/exit.c
kernel/fork.c
kernel/pid.c
kernel/power/snapshot.c
kernel/sched/fair.c
kernel/signal.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/synth_event_gen_test.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
kernel/workqueue.c
lib/bootconfig.c
lib/crypto/chacha20poly1305.c
mm/huge_memory.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mprotect.c
mm/shmem.c
mm/z3fold.c
net/batman-adv/bat_iv_ogm.c
net/bridge/br_device.c
net/caif/caif_dev.c
net/core/dev.c
net/core/devlink.c
net/core/netclassid_cgroup.c
net/core/sock.c
net/dsa/dsa_priv.h
net/dsa/port.c
net/dsa/slave.c
net/ethtool/bitset.c
net/ethtool/bitset.h
net/ieee802154/nl_policy.c
net/ipv4/cipso_ipv4.c
net/ipv4/gre_demux.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/raw_diag.c
net/ipv4/tcp_input.c
net/ipv4/udp_diag.c
net/ipv6/addrconf.c
net/ipv6/ipv6_sockglue.c
net/ipv6/seg6_iptunnel.c
net/ipv6/seg6_local.c
net/mac80211/mesh_hwmp.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mptcp/options.c
net/mptcp/protocol.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nft_chain_nat.c
net/netfilter/nft_payload.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_tunnel.c
net/netfilter/x_tables.c
net/netfilter/xt_hashlimit.c
net/netfilter/xt_recent.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/nfc/hci/core.c
net/nfc/netlink.c
net/openvswitch/datapath.c
net/packet/af_packet.c
net/sched/act_api.c
net/sched/sch_fq.c
net/sched/sch_taprio.c
net/sctp/diag.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/tipc/netlink.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/nl80211.c
net/wireless/reg.c
scripts/Makefile.lib
scripts/parse-maintainers.pl [changed mode: 0644->0755]
sound/mips/sgio2audio.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/Kconfig
sound/soc/codecs/pcm512x.c
sound/soc/codecs/rt1015.c
sound/soc/codecs/tas2562.c
sound/soc/intel/skylake/skl-debug.c
sound/soc/intel/skylake/skl-ssp-clk.c
sound/soc/meson/g12a-tohdmitx.c
sound/soc/soc-component.c
sound/soc/soc-compress.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/ipc.c
sound/soc/stm/stm32_sai_sub.c
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/bootconfig/include/linux/printk.h
tools/bootconfig/main.c
tools/bootconfig/samples/bad-mixed-kv1.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-mixed-kv2.bconf [new file with mode: 0644]
tools/bootconfig/samples/bad-samekey.bconf [new file with mode: 0644]
tools/bootconfig/test-bootconfig.sh
tools/perf/Documentation/perf-config.txt
tools/perf/arch/arm/util/cs-etm.c
tools/perf/arch/arm64/util/arm-spe.c
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
tools/perf/arch/x86/util/intel-bts.c
tools/perf/arch/x86/util/intel-pt.c
tools/perf/builtin-annotate.c
tools/perf/builtin-probe.c
tools/perf/builtin-report.c
tools/perf/builtin-top.c
tools/perf/include/bpf/pid_filter.h
tools/perf/include/bpf/stdio.h
tools/perf/include/bpf/unistd.h
tools/perf/tests/shell/lib/probe_vfs_getname.sh
tools/perf/ui/browsers/annotate.c
tools/perf/ui/gtk/annotate.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/config.c
tools/perf/util/config.h
tools/perf/util/probe-file.c
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/livepatch/Makefile
tools/testing/selftests/lkdtm/.gitignore [new file with mode: 0644]
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/mptcp/Makefile
tools/testing/selftests/netfilter/nft_concat_range.sh
tools/testing/selftests/pidfd/.gitignore
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rtc/Makefile
tools/testing/selftests/tc-testing/config
virt/kvm/arm/arm.c
virt/kvm/arm/trace.h

index 196ca31..6ec5558 100644 (file)
@@ -86,6 +86,8 @@ ForEachMacros:
   - 'bio_for_each_segment_all'
   - 'bio_list_for_each'
   - 'bip_for_each_vec'
+  - 'bitmap_for_each_clear_region'
+  - 'bitmap_for_each_set_region'
   - 'blkg_for_each_descendant_post'
   - 'blkg_for_each_descendant_pre'
   - 'blk_queue_for_each_rl'
@@ -115,6 +117,7 @@ ForEachMacros:
   - 'drm_client_for_each_connector_iter'
   - 'drm_client_for_each_modeset'
   - 'drm_connector_for_each_possible_encoder'
+  - 'drm_for_each_bridge_in_chain'
   - 'drm_for_each_connector_iter'
   - 'drm_for_each_crtc'
   - 'drm_for_each_encoder'
@@ -136,9 +139,10 @@ ForEachMacros:
   - 'for_each_bio'
   - 'for_each_board_func_rsrc'
   - 'for_each_bvec'
+  - 'for_each_card_auxs'
+  - 'for_each_card_auxs_safe'
   - 'for_each_card_components'
-  - 'for_each_card_links'
-  - 'for_each_card_links_safe'
+  - 'for_each_card_pre_auxs'
   - 'for_each_card_prelinks'
   - 'for_each_card_rtds'
   - 'for_each_card_rtds_safe'
@@ -166,6 +170,7 @@ ForEachMacros:
   - 'for_each_dpcm_fe'
   - 'for_each_drhd_unit'
   - 'for_each_dss_dev'
+  - 'for_each_efi_handle'
   - 'for_each_efi_memory_desc'
   - 'for_each_efi_memory_desc_in_map'
   - 'for_each_element'
@@ -190,6 +195,7 @@ ForEachMacros:
   - 'for_each_lru'
   - 'for_each_matching_node'
   - 'for_each_matching_node_and_match'
+  - 'for_each_member'
   - 'for_each_memblock'
   - 'for_each_memblock_type'
   - 'for_each_memcg_cache_index'
@@ -200,9 +206,11 @@ ForEachMacros:
   - 'for_each_msi_entry'
   - 'for_each_msi_entry_safe'
   - 'for_each_net'
+  - 'for_each_net_continue_reverse'
   - 'for_each_netdev'
   - 'for_each_netdev_continue'
   - 'for_each_netdev_continue_rcu'
+  - 'for_each_netdev_continue_reverse'
   - 'for_each_netdev_feature'
   - 'for_each_netdev_in_bond_rcu'
   - 'for_each_netdev_rcu'
@@ -254,10 +262,10 @@ ForEachMacros:
   - 'for_each_reserved_mem_region'
   - 'for_each_rtd_codec_dai'
   - 'for_each_rtd_codec_dai_rollback'
-  - 'for_each_rtdcom'
-  - 'for_each_rtdcom_safe'
+  - 'for_each_rtd_components'
   - 'for_each_set_bit'
   - 'for_each_set_bit_from'
+  - 'for_each_set_clump8'
   - 'for_each_sg'
   - 'for_each_sg_dma_page'
   - 'for_each_sg_page'
@@ -267,6 +275,7 @@ ForEachMacros:
   - 'for_each_subelement_id'
   - '__for_each_thread'
   - 'for_each_thread'
+  - 'for_each_wakeup_source'
   - 'for_each_zone'
   - 'for_each_zone_zonelist'
   - 'for_each_zone_zonelist_nodemask'
@@ -330,6 +339,7 @@ ForEachMacros:
   - 'list_for_each'
   - 'list_for_each_codec'
   - 'list_for_each_codec_safe'
+  - 'list_for_each_continue'
   - 'list_for_each_entry'
   - 'list_for_each_entry_continue'
   - 'list_for_each_entry_continue_rcu'
@@ -351,6 +361,7 @@ ForEachMacros:
   - 'llist_for_each_entry'
   - 'llist_for_each_entry_safe'
   - 'llist_for_each_safe'
+  - 'mci_for_each_dimm'
   - 'media_device_for_each_entity'
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
@@ -444,10 +455,16 @@ ForEachMacros:
   - 'virtio_device_for_each_vq'
   - 'xa_for_each'
   - 'xa_for_each_marked'
+  - 'xa_for_each_range'
   - 'xa_for_each_start'
   - 'xas_for_each'
   - 'xas_for_each_conflict'
   - 'xas_for_each_marked'
+  - 'xbc_array_for_each_value'
+  - 'xbc_for_each_key_value'
+  - 'xbc_node_for_each_array_value'
+  - 'xbc_node_for_each_child'
+  - 'xbc_node_for_each_key_value'
   - 'zorro_for_each_dev'
 
 #IncludeBlocks: Preserve # Unknown to clang-format-5.0
diff --git a/CREDITS b/CREDITS
index a97d328..032b599 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -567,6 +567,11 @@ D: Original author of Amiga FFS filesystem
 S: Orlando, Florida
 S: USA
 
+N: Paul Burton
+E: paulburton@kernel.org
+W: https://pburton.com
+D: MIPS maintainer 2018-2020
+
 N: Lennert Buytenhek
 E: kernel@wantstofly.org
 D: Original (2.4) rewrite of the ethernet bridging code
index 21d233c..98fe5c3 100644 (file)
@@ -18,7 +18,7 @@ may look as follows::
 
  $ ls -l /sys/bus/acpi/devices/INT3404:00/
  total 0
-...
+ ...
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state0
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state1
  -r--r--r-- 1 root root 4096 Dec 13 20:38 state10
@@ -38,7 +38,7 @@ where each of the "state*" files represents one performance state of the fan
 and contains a colon-separated list of 5 integer numbers (fields) with the
 following interpretation::
 
-control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw
+  control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw
 
 * ``control_percent``: The percent value to be used to set the fan speed to a
   specific level using the _FSL object (0-100).
index b342a67..cf2edcd 100644 (file)
@@ -62,6 +62,30 @@ Or more shorter, written as following::
 In both styles, same key words are automatically merged when parsing it
 at boot time. So you can append similar trees or key-values.
 
+Same-key Values
+---------------
+
+It is prohibited that two or more values or arrays share a same-key.
+For example,::
+
+ foo = bar, baz
+ foo = qux  # !ERROR! we can not re-define same key
+
+If you want to append the value to existing key as an array member,
+you can use ``+=`` operator. For example::
+
+ foo = bar, baz
+ foo += qux
+
+In this case, the key ``foo`` has ``bar``, ``baz`` and ``qux``.
+
+However, a sub-key and a value can not co-exist under a parent key.
+For example, following config is NOT allowed.::
+
+ foo = value1
+ foo.bar = value2 # !ERROR! subkey "bar" and value "value1" can NOT co-exist
+
+
 Comments
 --------
 
@@ -102,9 +126,13 @@ Boot Kernel With a Boot Config
 ==============================
 
 Since the boot configuration file is loaded with initrd, it will be added
-to the end of the initrd (initramfs) image file. The Linux kernel decodes
-the last part of the initrd image in memory to get the boot configuration
-data.
+to the end of the initrd (initramfs) image file with size, checksum and
+12-byte magic word as below.
+
+[initrd][bootconfig][size(u32)][checksum(u32)][#BOOTCONFIG\n]
+
+The Linux kernel decodes the last part of the initrd image in memory to
+get the boot configuration data.
 Because of this "piggyback" method, there is no need to change or
 update the boot loader and the kernel image itself.
 
index dbc22d6..c07815d 100644 (file)
                        dynamic table installation which will install SSDT
                        tables to /sys/firmware/acpi/tables/dynamic.
 
+       acpi_no_watchdog        [HW,ACPI,WDT]
+                       Ignore the ACPI-based watchdog interface (WDAT) and let
+                       a native driver control the watchdog device instead.
+
        acpi_rsdp=      [ACPI,EFI,KEXEC]
                        Pass the RSDP address to the kernel, mostly used
                        on machines running EFI runtime service to boot the
index 7cd56a1..607758a 100644 (file)
@@ -551,6 +551,7 @@ options to your ``.config``:
 Once the kernel is built and installed, a simple
 
 .. code-block:: bash
+
        modprobe example-test
 
 ...will run the tests.
index f493d69..dc102c4 100644 (file)
@@ -102,7 +102,7 @@ Required sub-node properties:
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/power/power-domain.yaml
 [3] Documentation/devicetree/bindings/thermal/thermal.txt
-[4] Documentation/devicetree/bindings/sram/sram.txt
+[4] Documentation/devicetree/bindings/sram/sram.yaml
 [5] Documentation/devicetree/bindings/reset/reset.txt
 
 Example:
index 7b83ef4..dd04d9d 100644 (file)
@@ -109,7 +109,7 @@ Required properties:
 [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/thermal/thermal.txt
-[3] Documentation/devicetree/bindings/sram/sram.txt
+[3] Documentation/devicetree/bindings/sram/sram.yaml
 [4] Documentation/devicetree/bindings/power/power-domain.yaml
 
 Example:
index b82b6a0..8c7a490 100644 (file)
@@ -62,7 +62,7 @@ Timer node:
 
 Syscon reboot node:
 
-See Documentation/devicetree/bindings/power/reset/syscon-reboot.txt for the
+See Documentation/devicetree/bindings/power/reset/syscon-reboot.yaml for the
 detailed list of properties, the two values defined below are specific to the
 BCM6328-style timer:
 
index 7a9c3ce..0d5b610 100644 (file)
@@ -216,7 +216,7 @@ properties:
     $ref: '/schemas/types.yaml#/definitions/phandle-array'
     description: |
       List of phandles to idle state nodes supported
-      by this cpu (see ./idle-states.txt).
+      by this cpu (see ./idle-states.yaml).
 
   capacity-dmips-mhz:
     $ref: '/schemas/types.yaml#/definitions/uint32'
index a8e0b4a..0e17e1f 100644 (file)
@@ -160,7 +160,7 @@ properties:
         items:
           - enum:
               - armadeus,imx6dl-apf6      # APF6 (Solo) SoM
-              - armadeus,imx6dl-apf6dldev # APF6 (Solo) SoM on APF6Dev board
+              - armadeus,imx6dl-apf6dev   # APF6 (Solo) SoM on APF6Dev board
               - eckelmann,imx6dl-ci4x10
               - emtrion,emcon-mx6         # emCON-MX6S or emCON-MX6DL SoM
               - emtrion,emcon-mx6-avari   # emCON-MX6S or emCON-MX6DL SoM on Avari Base
index 115c5be..8defacc 100644 (file)
@@ -1,7 +1,7 @@
 * Hisilicon Hi3519 System Controller Block
 
 This bindings use the following binding:
-Documentation/devicetree/bindings/mfd/syscon.txt
+Documentation/devicetree/bindings/mfd/syscon.yaml
 
 Required properties:
 - compatible: "hisilicon,hi3519-sysctrl".
index 06df04c..6ce0b21 100644 (file)
@@ -81,4 +81,4 @@ Example:
                };
        };
 
-[1]. Documentation/devicetree/bindings/arm/idle-states.txt
+[1]. Documentation/devicetree/bindings/arm/idle-states.yaml
index f301e63..e41490e 100644 (file)
@@ -17,7 +17,7 @@ am335x and am437x only:
 - pm-sram: Phandles to ocmcram nodes to be used for power management.
           First should be type 'protect-exec' for the driver to use to copy
           and run PM functions, second should be regular pool to be used for
-          data region for code. See Documentation/devicetree/bindings/sram/sram.txt
+          data region for code. See Documentation/devicetree/bindings/sram/sram.yaml
           for more details.
 
 Examples:
index 8ef8542..5e66934 100644 (file)
@@ -100,13 +100,14 @@ properties:
       bindings in [1]) must specify this property.
 
       [1] Kernel documentation - ARM idle states bindings
-        Documentation/devicetree/bindings/arm/idle-states.txt
-
-  "#power-domain-cells":
-    description:
-      The number of cells in a PM domain specifier as per binding in [3].
-      Must be 0 as to represent a single PM domain.
+        Documentation/devicetree/bindings/arm/idle-states.yaml
 
+patternProperties:
+  "^power-domain-":
+    allOf:
+      - $ref: "../power/power-domain.yaml#"
+    type: object
+    description: |
       ARM systems can have multiple cores, sometimes in an hierarchical
       arrangement. This often, but not always, maps directly to the processor
       power topology of the system. Individual nodes in a topology have their
@@ -122,14 +123,8 @@ properties:
       helps to implement support for OSI mode and OS implementations may choose
       to mandate it.
 
-      [3] Documentation/devicetree/bindings/power/power_domain.txt
-      [4] Documentation/devicetree/bindings/power/domain-idle-state.txt
-
-  power-domains:
-    $ref: '/schemas/types.yaml#/definitions/phandle-array'
-    description:
-      List of phandles and PM domain specifiers, as defined by bindings of the
-      PM domain provider.
+      [3] Documentation/devicetree/bindings/power/power-domain.yaml
+      [4] Documentation/devicetree/bindings/power/domain-idle-state.yaml
 
 required:
   - compatible
@@ -199,7 +194,7 @@ examples:
 
       CPU0: cpu@0 {
         device_type = "cpu";
-        compatible = "arm,cortex-a53", "arm,armv8";
+        compatible = "arm,cortex-a53";
         reg = <0x0>;
         enable-method = "psci";
         power-domains = <&CPU_PD0>;
@@ -208,7 +203,7 @@ examples:
 
       CPU1: cpu@1 {
         device_type = "cpu";
-        compatible = "arm,cortex-a57", "arm,armv8";
+        compatible = "arm,cortex-a53";
         reg = <0x100>;
         enable-method = "psci";
         power-domains = <&CPU_PD1>;
@@ -224,6 +219,9 @@ examples:
           exit-latency-us = <10>;
           min-residency-us = <100>;
         };
+      };
+
+      domain-idle-states {
 
         CLUSTER_RET: cluster-retention {
           compatible = "domain-idle-state";
@@ -247,19 +245,19 @@ examples:
       compatible = "arm,psci-1.0";
       method = "smc";
 
-      CPU_PD0: cpu-pd0 {
+      CPU_PD0: power-domain-cpu0 {
         #power-domain-cells = <0>;
         domain-idle-states = <&CPU_PWRDN>;
         power-domains = <&CLUSTER_PD>;
       };
 
-      CPU_PD1: cpu-pd1 {
+      CPU_PD1: power-domain-cpu1 {
         #power-domain-cells = <0>;
         domain-idle-states =  <&CPU_PWRDN>;
         power-domains = <&CLUSTER_PD>;
       };
 
-      CLUSTER_PD: cluster-pd {
+      CLUSTER_PD: power-domain-cluster {
         #power-domain-cells = <0>;
         domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>;
       };
index 68917bb..55f7938 100644 (file)
@@ -52,7 +52,7 @@ required:
 
 examples:
   - |
-    mlahb: ahb {
+    mlahb: ahb@38000000 {
       compatible = "st,mlahb", "simple-bus";
       #address-cells = <1>;
       #size-cells = <1>;
index 9fe11ce..8097361 100644 (file)
@@ -70,7 +70,6 @@ examples:
         #size-cells = <0>;
 
         pmic@3e3 {
-            compatible = "...";
             reg = <0x3e3>;
 
             /* ... */
index 69cfa4a..c604822 100644 (file)
@@ -40,7 +40,7 @@ additionalProperties: false
 
 examples:
   - |
-    osc24M: clk@01c20050 {
+    osc24M: clk@1c20050 {
         #clock-cells = <0>;
         compatible = "allwinner,sun4i-a10-osc-clk";
         reg = <0x01c20050 0x4>;
index 07f38de..43963c3 100644 (file)
@@ -41,7 +41,7 @@ additionalProperties: false
 
 examples:
   - |
-    clk@0600005c {
+    clk@600005c {
         #clock-cells = <0>;
         compatible = "allwinner,sun9i-a80-gt-clk";
         reg = <0x0600005c 0x4>;
index 17f8717..3647007 100644 (file)
@@ -42,7 +42,7 @@ properties:
       be part of GCC and hence the TSENS properties can also be part
       of the GCC/clock-controller node.
       For more details on the TSENS properties please refer
-      Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+      Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
 
   nvmem-cell-names:
     minItems: 1
index 5d5d396..6009324 100644 (file)
@@ -49,11 +49,7 @@ examples:
         resets = <&tcon_ch0_clk 0>;
 
         port {
-            #address-cells = <1>;
-            #size-cells = <0>;
-
-            tve0_in_tcon0: endpoint@0 {
-                reg = <0>;
+            tve0_in_tcon0: endpoint {
                 remote-endpoint = <&tcon0_out_tve0>;
             };
         };
index 6d72b3d..c211038 100644 (file)
@@ -79,21 +79,15 @@ examples:
           #size-cells = <0>;
 
           anx6345_in: port@0 {
-            #address-cells = <1>;
-            #size-cells = <0>;
             reg = <0>;
-            anx6345_in_tcon0: endpoint@0 {
-              reg = <0>;
+            anx6345_in_tcon0: endpoint {
               remote-endpoint = <&tcon0_out_anx6345>;
             };
           };
 
           anx6345_out: port@1 {
-            #address-cells = <1>;
-            #size-cells = <0>;
             reg = <1>;
-            anx6345_out_panel: endpoint@0 {
-              reg = <0>;
+            anx6345_out_panel: endpoint {
               remote-endpoint = <&panel_in_edp>;
             };
           };
index 4ebcea7..a614644 100644 (file)
@@ -37,6 +37,8 @@ examples:
     dsi@ff450000 {
         #address-cells = <1>;
         #size-cells = <0>;
+        reg = <0xff450000 0x1000>;
+
         panel@0 {
             compatible = "leadtek,ltk500hd1829";
             reg = <0>;
index 186e5e1..22c91be 100644 (file)
@@ -37,6 +37,8 @@ examples:
     dsi@ff450000 {
         #address-cells = <1>;
         #size-cells = <0>;
+        reg = <0xff450000 0x1000>;
+
         panel@0 {
             compatible = "xinpeng,xpp055c272";
             reg = <0>;
index 678776b..1db608c 100644 (file)
@@ -174,10 +174,6 @@ examples:
       };
     };
 
-    soc@1c00000 {
-      lcdc0: lcdc@1c0c000 {
-        compatible = "allwinner,sun4i-a10-lcdc";
-      };
-    };
+    lcdc0: lcdc { };
 
 ...
index 7bf1bb4..aac617a 100644 (file)
@@ -37,7 +37,7 @@ Optional nodes:
    supports a single port with a single endpoint.
 
  - See also Documentation/devicetree/bindings/display/tilcdc/panel.txt and
-   Documentation/devicetree/bindings/display/tilcdc/tfp410.txt for connecting
+   Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt for connecting
    tfp410 DVI encoder or lcd panel to lcdc
 
 [1] There is an errata about AM335x color wiring. For 16-bit color mode
index 8b5c346..34780d7 100644 (file)
@@ -143,7 +143,7 @@ examples:
             #size-cells = <2>;
             dma-coherent;
             dma-ranges;
-            ranges;
+            ranges = <0x0 0x30800000 0x0 0x30800000 0x0 0x05000000>;
 
             ti,sci-dev-id = <118>;
 
@@ -169,16 +169,4 @@ examples:
                 ti,sci-rm-range-rflow = <0x6>; /* GP RFLOW */
             };
         };
-
-        mcasp0: mcasp@02B00000 {
-            dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>;
-            dma-names = "tx", "rx";
-        };
-
-        crypto: crypto@4E00000 {
-            compatible = "ti,sa2ul-crypto";
-
-            dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>, <&main_udmap 0x4001>;
-            dma-names = "tx", "rx1", "rx2";
-        };
     };
index 4ea6a87..e8b99ad 100644 (file)
@@ -84,31 +84,31 @@ examples:
     gpu_opp_table: opp_table0 {
       compatible = "operating-points-v2";
 
-      opp@533000000 {
+      opp-533000000 {
         opp-hz = /bits/ 64 <533000000>;
         opp-microvolt = <1250000>;
       };
-      opp@450000000 {
+      opp-450000000 {
         opp-hz = /bits/ 64 <450000000>;
         opp-microvolt = <1150000>;
       };
-      opp@400000000 {
+      opp-400000000 {
         opp-hz = /bits/ 64 <400000000>;
         opp-microvolt = <1125000>;
       };
-      opp@350000000 {
+      opp-350000000 {
         opp-hz = /bits/ 64 <350000000>;
         opp-microvolt = <1075000>;
       };
-      opp@266000000 {
+      opp-266000000 {
         opp-hz = /bits/ 64 <266000000>;
         opp-microvolt = <1025000>;
       };
-      opp@160000000 {
+      opp-160000000 {
         opp-hz = /bits/ 64 <160000000>;
         opp-microvolt = <925000>;
       };
-      opp@100000000 {
+      opp-100000000 {
         opp-hz = /bits/ 64 <100000000>;
         opp-microvolt = <912500>;
       };
index 36f59b3..8d966f3 100644 (file)
@@ -138,31 +138,31 @@ examples:
     gpu_opp_table: opp_table0 {
       compatible = "operating-points-v2";
 
-      opp@533000000 {
+      opp-533000000 {
         opp-hz = /bits/ 64 <533000000>;
         opp-microvolt = <1250000>;
       };
-      opp@450000000 {
+      opp-450000000 {
         opp-hz = /bits/ 64 <450000000>;
         opp-microvolt = <1150000>;
       };
-      opp@400000000 {
+      opp-400000000 {
         opp-hz = /bits/ 64 <400000000>;
         opp-microvolt = <1125000>;
       };
-      opp@350000000 {
+      opp-350000000 {
         opp-hz = /bits/ 64 <350000000>;
         opp-microvolt = <1075000>;
       };
-      opp@266000000 {
+      opp-266000000 {
         opp-hz = /bits/ 64 <266000000>;
         opp-microvolt = <1025000>;
       };
-      opp@160000000 {
+      opp-160000000 {
         opp-hz = /bits/ 64 <160000000>;
         opp-microvolt = <925000>;
       };
-      opp@100000000 {
+      opp-100000000 {
         opp-hz = /bits/ 64 <100000000>;
         opp-microvolt = <912500>;
       };
index f46de17..cc3c8ea 100644 (file)
@@ -123,7 +123,7 @@ examples:
         samsung,syscon-phandle = <&pmu_system_controller>;
 
         /* NTC thermistor is a hwmon device */
-        ncp15wb473@0 {
+        ncp15wb473 {
             compatible = "murata,ncp15wb473";
             pullup-uv = <1800000>;
             pullup-ohm = <47000>;
index d7c3262..c99ed39 100644 (file)
@@ -62,7 +62,7 @@ required:
 
 examples:
 - |
-    i2c@00000000 {
+    i2c {
       #address-cells = <1>;
       #size-cells = <0>;
       gt928@5d {
index c864a46..f502121 100644 (file)
@@ -1,7 +1,7 @@
 Texas Instruments TWL family (twl4030) pwrbutton module
 
 This module is part of the TWL4030. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/twl-familly.txt.
+chip see Documentation/devicetree/bindings/mfd/twl-family.txt.
 
 This module provides a simple power button event via an Interrupt.
 
index d97d099..c60b994 100644 (file)
@@ -85,7 +85,7 @@ properties:
         # LED will act as a back-light, controlled by the framebuffer system
       - backlight
         # LED will turn on (but for leds-gpio see "default-state" property in
-        # Documentation/devicetree/bindings/leds/leds-gpio.txt)
+        # Documentation/devicetree/bindings/leds/leds-gpio.yaml)
       - default-on
         # LED "double" flashes at a load average based rate
       - heartbeat
index cf1ea40..c7af6f7 100644 (file)
@@ -5,7 +5,7 @@ where single bits in a certain register can turn on/off a
 single LED. The register bit LEDs appear as children to the
 syscon device, with the proper compatible string. For the
 syscon bindings see:
-Documentation/devicetree/bindings/mfd/syscon.txt
+Documentation/devicetree/bindings/mfd/syscon.yaml
 
 Each LED is represented as a sub-node of the syscon device. Each
 node's name represents the name of the corresponding LED.
index 1ea7841..5e06662 100644 (file)
@@ -177,7 +177,7 @@ examples:
         };
     };
 
-    i2c5: i2c@4807c000 {
+    i2c {
         clock-frequency = <400000>;
         #address-cells = <1>;
         #size-cells = <0>;
index 44d7146..63f674f 100644 (file)
@@ -32,7 +32,7 @@ Required only for "ti,emif-am3352" and "ti,emif-am4372":
 - sram                 : Phandles for generic sram driver nodes,
   first should be type 'protect-exec' for the driver to use to copy
   and run PM functions, second should be regular pool to be used for
-  data region for code. See Documentation/devicetree/bindings/sram/sram.txt
+  data region for code. See Documentation/devicetree/bindings/sram/sram.yaml
   for more details.
 
 Optional properties:
index 4a70f87..4803857 100644 (file)
@@ -97,14 +97,14 @@ examples:
             regulators {
                 compatible = "maxim,max77650-regulator";
 
-                max77650_ldo: regulator@0 {
+                max77650_ldo: regulator-ldo {
                     regulator-compatible = "ldo";
                     regulator-name = "max77650-ldo";
                     regulator-min-microvolt = <1350000>;
                     regulator-max-microvolt = <2937500>;
                 };
 
-                max77650_sbb0: regulator@1 {
+                max77650_sbb0: regulator-sbb0 {
                     regulator-compatible = "sbb0";
                     regulator-name = "max77650-sbb0";
                     regulator-min-microvolt = <800000>;
index 4f62143..a5ced46 100644 (file)
@@ -26,8 +26,8 @@ Required properties:
             ldo6, ldo7, ldo8
 
 - xxx-supply: Input voltage supply regulator.
-  These entries are require if regulators are enabled for a device. Missing of these
-  properties can cause the regulator registration fails.
+  These entries are required if regulators are enabled for a device. Missing these
+  properties can cause the regulator registration to fail.
   If some of input supply is powered through battery or always-on supply then
   also it is require to have these parameters with proper node handle of always
   on power supply.
index 088eff9..e0f901e 100644 (file)
@@ -20,7 +20,7 @@ RAVE SP consists of the following sub-devices:
 Device                          Description
 ------                          -----------
 rave-sp-wdt                    : Watchdog
-rave-sp-nvmem                  : Interface to onborad EEPROM
+rave-sp-nvmem                  : Interface to onboard EEPROM
 rave-sp-backlight              : Display backlight
 rave-sp-hwmon                  : Interface to onboard hardware sensors
 rave-sp-leds                   : Interface to onboard LEDs
index bb7e896..9134e9b 100644 (file)
@@ -26,7 +26,7 @@ For generic IOMMU bindings, see
 Documentation/devicetree/bindings/iommu/iommu.txt.
 
 For arm-smmu binding, see:
-Documentation/devicetree/bindings/iommu/arm,smmu.txt.
+Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
 
 Required properties:
 
index 3c0df40..8fded83 100644 (file)
@@ -370,6 +370,7 @@ examples:
     mmc3: mmc@1c12000 {
         #address-cells = <1>;
         #size-cells = <0>;
+        reg = <0x1c12000 0x200>;
         pinctrl-names = "default";
         pinctrl-0 = <&mmc3_pins_a>;
         vmmc-supply = <&reg_vmmc3>;
index f3893c4..d2eada5 100644 (file)
@@ -27,7 +27,7 @@ Required properties of NAND chips:
   - reg: shall contain the native Chip Select ids from 0 to max supported by
     the cadence nand flash controller
 
-See Documentation/devicetree/bindings/mtd/nand.txt for more details on
+See Documentation/devicetree/bindings/mtd/nand-controller.yaml for more details on
 generic bindings.
 
 Example:
index 48a7f91..88b57b0 100644 (file)
@@ -45,7 +45,7 @@ Optional properties:
   switch queue
 
 - resets: a single phandle and reset identifier pair. See
-  Documentation/devicetree/binding/reset/reset.txt for details.
+  Documentation/devicetree/bindings/reset/reset.txt for details.
 
 - reset-names: If the "reset" property is specified, this property should have
   the value "switch" to denote the switch reset line.
index 250f8d8..c00fb0d 100644 (file)
@@ -110,6 +110,13 @@ PROPERTIES
                Usage: required
                Definition: See soc/fsl/qman.txt and soc/fsl/bman.txt
 
+- fsl,erratum-a050385
+               Usage: optional
+               Value type: boolean
+               Definition: A boolean property. Indicates the presence of the
+               erratum A050385 which indicates that DMA transactions that are
+               split can result in a FMan lock.
+
 =============================================================================
 FMan MURAM Node
 
index b43c6c6..6598022 100644 (file)
@@ -76,6 +76,8 @@ examples:
       qfprom: eeprom@700000 {
           #address-cells = <1>;
           #size-cells = <1>;
+          reg = <0x00700000 0x100000>;
+
           wp-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
 
           /* ... */
index 020ef9e..94ac236 100644 (file)
@@ -86,7 +86,7 @@ examples:
     #include <dt-bindings/clock/sun4i-a10-ccu.h>
     #include <dt-bindings/reset/sun4i-a10-ccu.h>
 
-    usbphy: phy@01c13400 {
+    usbphy: phy@1c13400 {
         #phy-cells = <1>;
         compatible = "allwinner,sun4i-a10-usb-phy";
         reg = <0x01c13400 0x10>, <0x01c14800 0x4>, <0x01c1c800 0x4>;
index bb690e2..135c7df 100644 (file)
@@ -17,7 +17,7 @@ description: |+
                     "aspeed,ast2400-scu", "syscon", "simple-mfd"
 
   Refer to the the bindings described in
-  Documentation/devicetree/bindings/mfd/syscon.txt
+  Documentation/devicetree/bindings/mfd/syscon.yaml
 
 properties:
   compatible:
index f7f5d57..824f7fd 100644 (file)
@@ -18,7 +18,7 @@ description: |+
                        "aspeed,g5-scu", "syscon", "simple-mfd"
 
   Refer to the the bindings described in
-  Documentation/devicetree/bindings/mfd/syscon.txt
+  Documentation/devicetree/bindings/mfd/syscon.yaml
 
 properties:
   compatible:
index 3749fa2..ac8d1c3 100644 (file)
@@ -17,7 +17,7 @@ description: |+
                 "aspeed,ast2600-scu", "syscon", "simple-mfd"
 
   Refer to the the bindings described in
-  Documentation/devicetree/bindings/mfd/syscon.txt
+  Documentation/devicetree/bindings/mfd/syscon.yaml
 
 properties:
   compatible:
index 754ea7a..ef4de32 100644 (file)
@@ -248,7 +248,7 @@ examples:
       };
 
     //Example 3 pin groups
-      pinctrl@60020000 {
+      pinctrl {
         usart1_pins_a: usart1-0 {
                 pins1 {
                         pinmux = <STM32_PINMUX('A', 9, AF7)>;
index aab70e8..d3098c9 100644 (file)
@@ -18,7 +18,7 @@ description: |+
                 "amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon"
 
   Refer to the the bindings described in
-  Documentation/devicetree/bindings/mfd/syscon.txt
+  Documentation/devicetree/bindings/mfd/syscon.yaml
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.txt b/Documentation/devicetree/bindings/power/domain-idle-state.txt
deleted file mode 100644 (file)
index eefc7ed..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-PM Domain Idle State Node:
-
-A domain idle state node represents the state parameters that will be used to
-select the state when there are no active components in the domain.
-
-The state node has the following parameters -
-
-- compatible:
-       Usage: Required
-       Value type: <string>
-       Definition: Must be "domain-idle-state".
-
-- entry-latency-us
-       Usage: Required
-       Value type: <prop-encoded-array>
-       Definition: u32 value representing worst case latency in
-                   microseconds required to enter the idle state.
-                   The exit-latency-us duration may be guaranteed
-                   only after entry-latency-us has passed.
-
-- exit-latency-us
-       Usage: Required
-       Value type: <prop-encoded-array>
-       Definition: u32 value representing worst case latency
-                   in microseconds required to exit the idle state.
-
-- min-residency-us
-       Usage: Required
-       Value type: <prop-encoded-array>
-       Definition: u32 value representing minimum residency duration
-                   in microseconds after which the idle state will yield
-                   power benefits after overcoming the overhead in entering
-i                  the idle state.
diff --git a/Documentation/devicetree/bindings/power/domain-idle-state.yaml b/Documentation/devicetree/bindings/power/domain-idle-state.yaml
new file mode 100644 (file)
index 0000000..dfba1af
--- /dev/null
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/domain-idle-state.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PM Domain Idle States binding description
+
+maintainers:
+  - Ulf Hansson <ulf.hansson@linaro.org>
+
+description:
+  A domain idle state node represents the state parameters that will be used to
+  select the state when there are no active components in the PM domain.
+
+properties:
+  $nodename:
+    const: domain-idle-states
+
+patternProperties:
+  "^(cpu|cluster|domain)-":
+    type: object
+    description:
+      Each state node represents a domain idle state description.
+
+    properties:
+      compatible:
+        const: domain-idle-state
+
+      entry-latency-us:
+        description:
+          The worst case latency in microseconds required to enter the idle
+          state. Note that, the exit-latency-us duration may be guaranteed only
+          after the entry-latency-us has passed.
+
+      exit-latency-us:
+        description:
+          The worst case latency in microseconds required to exit the idle
+          state.
+
+      min-residency-us:
+        description:
+          The minimum residency duration in microseconds after which the idle
+          state will yield power benefits, after overcoming the overhead while
+          entering the idle state.
+
+    required:
+      - compatible
+      - entry-latency-us
+      - exit-latency-us
+      - min-residency-us
+
+examples:
+  - |
+
+    domain-idle-states {
+      domain_retention: domain-retention {
+        compatible = "domain-idle-state";
+        entry-latency-us = <20>;
+        exit-latency-us = <40>;
+        min-residency-us = <80>;
+      };
+    };
+...
index 455b573..6047aac 100644 (file)
@@ -25,22 +25,20 @@ description: |+
 
 properties:
   $nodename:
-    pattern: "^(power-controller|power-domain)(@.*)?$"
+    pattern: "^(power-controller|power-domain)([@-].*)?$"
 
   domain-idle-states:
     $ref: /schemas/types.yaml#/definitions/phandle-array
-    description:
-      A phandle of an idle-state that shall be soaked into a generic domain
-      power state. The idle state definitions are compatible with
-      domain-idle-state specified in
-      Documentation/devicetree/bindings/power/domain-idle-state.txt
-      phandles that are not compatible with domain-idle-state will be ignored.
-      The domain-idle-state property reflects the idle state of this PM domain
-      and not the idle states of the devices or sub-domains in the PM domain.
-      Devices and sub-domains have their own idle-states independent
-      of the parent domain's idle states. In the absence of this property,
-      the domain would be considered as capable of being powered-on
-      or powered-off.
+    description: |
+      Phandles of idle states that defines the available states for the
+      power-domain provider. The idle state definitions are compatible with the
+      domain-idle-state bindings, specified in ./domain-idle-state.yaml.
+
+      Note that, the domain-idle-state property reflects the idle states of this
+      PM domain and not the idle states of the devices or sub-domains in the PM
+      domain. Devices and sub-domains have their own idle states independent of
+      the parent domain's idle states. In the absence of this property, the
+      domain would be considered as capable of being powered-on or powered-off.
 
   operating-points-v2:
     $ref: /schemas/types.yaml#/definitions/phandle-array
index 5b09b2d..08497ef 100644 (file)
@@ -109,4 +109,4 @@ Example:
                required-opps = <&domain1_opp_1>;
        };
 
-[1]. Documentation/devicetree/bindings/power/domain-idle-state.txt
+[1]. Documentation/devicetree/bindings/power/domain-idle-state.yaml
index f5cdac8..8b00519 100644 (file)
@@ -161,7 +161,7 @@ The regulator node houses sub-nodes for each regulator within the device. Each
 sub-node is identified using the node's name, with valid values listed for each
 of the PMICs below.
 
-pm8005:
+pm8004:
        s2, s5
 
 pm8005:
index 92ff2e8..91a39a3 100644 (file)
@@ -191,7 +191,7 @@ patternProperties:
 
 examples:
   - |
-    xyzreg: regulator@0 {
+    xyzreg: regulator {
       regulator-min-microvolt = <1000000>;
       regulator-max-microvolt = <2500000>;
       regulator-always-on;
index 246dea8..8ac4372 100644 (file)
@@ -23,7 +23,11 @@ properties:
     description: Global reset register offset and bit offset.
     allOf:
       - $ref: /schemas/types.yaml#/definitions/uint32-array
-      - maxItems: 2
+    items:
+      - description: Register offset
+      - description: Register bit offset
+        minimum: 0
+        maximum: 31
 
   "#reset-cells":
     minimum: 2
index b4edaf7..2880d5d 100644 (file)
@@ -3,4 +3,4 @@ STMicroelectronics STM32MP1 Peripheral Reset Controller
 
 The RCC IP is both a reset and a clock controller.
 
-Please see Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt
+Please see Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml
index 944743d..c42b91e 100644 (file)
@@ -36,7 +36,7 @@ SAI subnodes required properties:
   - clock-names: Must contain "sai_ck".
        Must also contain "MCLK", if SAI shares a master clock,
        with a SAI set as MCLK clock provider.
-  - dmas: see Documentation/devicetree/bindings/dma/stm32-dma.txt
+  - dmas: see Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
   - dma-names: identifier string for each DMA request line
        "tx": if sai sub-block is configured as playback DAI
        "rx": if sai sub-block is configured as capture DAI
index 33826f2..ca91017 100644 (file)
@@ -10,7 +10,7 @@ Required properties:
   - clock-names: must contain "kclk"
   - interrupts: cpu DAI interrupt line
   - dmas: DMA specifiers for audio data DMA and iec control flow DMA
-    See STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt
+    See STM32 DMA bindings, Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
   - dma-names: two dmas have to be defined, "rx" and "rx-ctrl"
 
 Optional properties:
index f0d9796..e49ecbf 100644 (file)
@@ -49,7 +49,7 @@ properties:
   dmas:
     description: |
       DMA specifiers for tx and rx dma. DMA fifo mode must be used. See
-      the STM32 DMA bindings Documentation/devicetree/bindings/dma/stm32-dma.txt.
+      the STM32 DMA bindings Documentation/devicetree/bindings/dma/st,stm32-dma.yaml.
     items:
       - description: rx DMA channel
       - description: tx DMA channel
index 80bac7a..4b55094 100644 (file)
@@ -125,7 +125,7 @@ examples:
       #size-cells = <1>;
       ranges;
 
-      sram_a: sram@00000000 {
+      sram_a: sram@0 {
         compatible = "mmio-sram";
         reg = <0x00000000 0xc000>;
         #address-cells = <1>;
index d9fdf48..f3e68ed 100644 (file)
@@ -17,7 +17,7 @@ description: |+
                 "brcm,bcm2711-avs-monitor", "syscon", "simple-mfd"
 
   Refer to the the bindings described in
-  Documentation/devicetree/bindings/mfd/syscon.txt
+  Documentation/devicetree/bindings/mfd/syscon.yaml
 
 properties:
   compatible:
index 23e989e..d918cee 100644 (file)
@@ -87,7 +87,7 @@ additionalProperties: false
 
 examples:
   - |
-    timer {
+    timer@1c20c00 {
         compatible = "allwinner,sun4i-a10-timer";
         reg = <0x01c20c00 0x400>;
         interrupts = <22>,
index e5953e7..2104830 100644 (file)
@@ -151,8 +151,8 @@ The details of these operations are:
      Note that callbacks will always be invoked from the DMA
      engines tasklet, never from interrupt context.
 
-Optional: per descriptor metadata
----------------------------------
+  **Optional: per descriptor metadata**
+
   DMAengine provides two ways for metadata support.
 
   DESC_METADATA_CLIENT
@@ -199,12 +199,15 @@ Optional: per descriptor metadata
   DESC_METADATA_CLIENT
 
     - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
          construct the metadata in the client's buffer
       2. use dmaengine_desc_attach_metadata() to attach the buffer to the
          descriptor
       3. submit the transfer
+
     - DMA_DEV_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. use dmaengine_desc_attach_metadata() to attach the buffer to the
          descriptor
@@ -215,6 +218,7 @@ Optional: per descriptor metadata
   DESC_METADATA_ENGINE
 
     - DMA_MEM_TO_DEV / DEV_MEM_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. use dmaengine_desc_get_metadata_ptr() to get the pointer to the
          engine's metadata area
@@ -222,7 +226,9 @@ Optional: per descriptor metadata
       4. use dmaengine_desc_set_metadata_len()  to tell the DMA engine the
          amount of data the client has placed into the metadata buffer
       5. submit the transfer
+
     - DMA_DEV_TO_MEM:
+
       1. prepare the descriptor (dmaengine_prep_*)
       2. submit the transfer
       3. on transfer completion, use dmaengine_desc_get_metadata_ptr() to get
@@ -278,8 +284,8 @@ Optional: per descriptor metadata
 
       void dma_async_issue_pending(struct dma_chan *chan);
 
-Further APIs:
--------------
+Further APIs
+------------
 
 1. Terminate APIs
 
index dc497b9..55336a4 100644 (file)
@@ -164,9 +164,9 @@ file.
        void __iomem *base;
     };
 
-    struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
-                                    struct dentry *parent,
-                                    struct debugfs_regset32 *regset);
+    debugfs_create_regset32(const char *name, umode_t mode,
+                           struct dentry *parent,
+                           struct debugfs_regset32 *regset);
 
     void debugfs_print_regs32(struct seq_file *s, struct debugfs_reg32 *regs,
                         int nregs, void __iomem *base, char *prefix);
index f185060..26c0939 100644 (file)
@@ -850,3 +850,11 @@ business doing so.
 d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are
 very suspect (and won't work in modules).  Such uses are very likely to
 be misspelled d_alloc_anon().
+
+---
+
+**mandatory**
+
+[should've been added in 2016] stale comment in finish_open() nonwithstanding,
+failure exits in ->atomic_open() instances should *NOT* fput() the file,
+no matter what.  Everything is handled by the caller.
index c81e0b4..471be1e 100644 (file)
@@ -20,8 +20,7 @@ Usage Notes
 -----------
 
 This driver does not auto-detect devices. You will have to instantiate the
-devices explicitly. Please see Documentation/i2c/instantiating-devices for
-details.
+devices explicitly. Please see :doc:`/i2c/instantiating-devices` for details.
 
 
 Sysfs entries
index 0e0eb2c..6bc126a 100644 (file)
@@ -765,7 +765,7 @@ is not sufficient this sometimes needs to be explicit.
        Example::
 
                #arch/x86/boot/Makefile
-               subdir- := compressed/
+               subdir- := compressed
 
 The above assignment instructs kbuild to descend down in the
 directory compressed/ when "make clean" is executed.
@@ -1379,9 +1379,6 @@ See subsequent chapter for the syntax of the Kbuild file.
        in arch/$(ARCH)/include/(uapi/)/asm, Kbuild will automatically generate
        a wrapper of the asm-generic one.
 
-       The convention is to list one subdir per line and
-       preferably in alphabetic order.
-
 8 Kbuild Variables
 ==================
 
index 1a7683e..8b46e85 100644 (file)
@@ -40,9 +40,6 @@ example usage
     # Delete a snapshot using:
     $ devlink region del pci/0000:00:05.0/cr-space snapshot 1
 
-    # Trigger (request) a snapshot be taken:
-    $ devlink region trigger pci/0000:00:05.0/cr-space
-
     # Dump a snapshot:
     $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
     0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
index 06c97dc..e143ab7 100644 (file)
@@ -8,9 +8,9 @@ Overview
 ========
 
 The net_failover driver provides an automated failover mechanism via APIs
-to create and destroy a failover master netdev and mananges a primary and
+to create and destroy a failover master netdev and manages a primary and
 standby slave netdevs that get registered via the generic failover
-infrastructrure.
+infrastructure.
 
 The failover netdev acts a master device and controls 2 slave devices. The
 original paravirtual interface is registered as 'standby' slave netdev and
@@ -29,7 +29,7 @@ virtio-net accelerated datapath: STANDBY mode
 =============================================
 
 net_failover enables hypervisor controlled accelerated datapath to virtio-net
-enabled VMs in a transparent manner with no/minimal guest userspace chanages.
+enabled VMs in a transparent manner with no/minimal guest userspace changes.
 
 To support this, the hypervisor needs to enable VIRTIO_NET_F_STANDBY
 feature on the virtio-net interface and assign the same MAC address to both
index 1e4735c..2561060 100644 (file)
@@ -487,8 +487,9 @@ phy_register_fixup_for_id()::
 The stubs set one of the two matching criteria, and set the other one to
 match anything.
 
-When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module,
-unregister fixup and free allocate memory are required.
+When phy_register_fixup() or \*_for_uid()/\*_for_id() is called at module load
+time, the module needs to unregister the fixup and free allocated memory when
+it's unloaded.
 
 Call one of following function before unloading module::
 
index f2a0147..eec6169 100644 (file)
@@ -159,7 +159,7 @@ Socket Interface
        set SO_RDS_TRANSPORT on a socket for which the transport has
        been previously attached explicitly (by SO_RDS_TRANSPORT) or
        implicitly (via bind(2)) will return an error of EOPNOTSUPP.
-       An attempt to set SO_RDS_TRANSPPORT to RDS_TRANS_NONE will
+       An attempt to set SO_RDS_TRANSPORT to RDS_TRANS_NONE will
        always return EINVAL.
 
 RDMA for RDS
index 002e427..ced8a80 100644 (file)
@@ -13,7 +13,6 @@ Power Management
     drivers-testing
     energy-model
     freezing-of-tasks
-    interface
     opp
     pci
     pm_qos_interface
index 7daf513..e54c44c 100644 (file)
@@ -30,4 +30,4 @@ if [ -n "$parallel" ] ; then
        parallel="-j$parallel"
 fi
 
-exec "$sphinx" "$parallel" "$@"
+exec "$sphinx" $parallel "$@"
index 97a72a5..ebd383f 100644 (file)
@@ -4611,35 +4611,38 @@ unpins the VPA pages and releases all the device pages that are used to
 track the secure pages by hypervisor.
 
 4.122 KVM_S390_NORMAL_RESET
+---------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the cpu reset definition in the POP (Principles Of Operation).
 
 4.123 KVM_S390_INITIAL_RESET
+----------------------------
 
-Capability: none
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: none
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the initial cpu reset definition in the POP. However, the cpu is not
 put into ESA mode. This reset is a superset of the normal reset.
 
 4.124 KVM_S390_CLEAR_RESET
+--------------------------
 
-Capability: KVM_CAP_S390_VCPU_RESETS
-Architectures: s390
-Type: vcpu ioctl
-Parameters: none
-Returns: 0
+:Capability: KVM_CAP_S390_VCPU_RESETS
+:Architectures: s390
+:Type: vcpu ioctl
+:Parameters: none
+:Returns: 0
 
 This ioctl resets VCPU registers and control structures according to
 the clear cpu reset definition in the POP. However, the cpu is not put
index a8de2fb..265d9e9 100644 (file)
@@ -19,7 +19,6 @@ x86-specific Documentation
    tlb
    mtrr
    pat
-   intel_mpx
    intel-iommu
    intel_txt
    amd-memory-encryption
index fcd79fc..cc1d18c 100644 (file)
@@ -693,7 +693,7 @@ ALLWINNER CPUFREQ DRIVER
 M:     Yangtao Li <tiny.windzz@gmail.com>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt
+F:     Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
 F:     drivers/cpufreq/sun50i-cpufreq-nvmem.c
 
 ALLWINNER CRYPTO DRIVERS
@@ -4017,7 +4017,7 @@ M:        Cheng-Yi Chiang <cychiang@chromium.org>
 S:     Maintained
 R:     Enric Balletbo i Serra <enric.balletbo@collabora.com>
 R:     Guenter Roeck <groeck@chromium.org>
-F:     Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
+F:     Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
 F:     sound/soc/codecs/cros_ec_codec.*
 
 CIRRUS LOGIC AUDIO CODEC DRIVERS
@@ -4073,7 +4073,6 @@ F:        drivers/scsi/snic/
 CISCO VIC ETHERNET NIC DRIVER
 M:     Christian Benvenuti <benve@cisco.com>
 M:     Govindarajulu Varadarajan <_govind@gmx.com>
-M:     Parvi Kaustubhi <pkaustub@cisco.com>
 S:     Supported
 F:     drivers/net/ethernet/cisco/enic/
 
@@ -4475,7 +4474,7 @@ L:        linux-media@vger.kernel.org
 T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/platform/sunxi/sun6i-csi/
-F:     Documentation/devicetree/bindings/media/sun6i-csi.txt
+F:     Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
 
 CW1200 WLAN driver
 M:     Solomon Peachy <pizza@shaftnet.org>
@@ -4572,7 +4571,7 @@ F:        drivers/infiniband/hw/cxgb4/
 F:     include/uapi/rdma/cxgb4-abi.h
 
 CXGB4VF ETHERNET DRIVER (CXGB4VF)
-M:     Casey Leedom <leedom@chelsio.com>
+M:     Vishal Kulkarni <vishal@gmail.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
@@ -5668,7 +5667,7 @@ L:        dri-devel@lists.freedesktop.org
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 S:     Maintained
 F:     drivers/gpu/drm/stm
-F:     Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
+F:     Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
 
 DRM DRIVERS FOR TI LCDC
 M:     Jyri Sarha <jsarha@ti.com>
@@ -6198,7 +6197,6 @@ S:        Supported
 F:     drivers/scsi/be2iscsi/
 
 Emulex 10Gbps NIC BE2, BE3-R, Lancer, Skyhawk-R DRIVER (be2net)
-M:     Sathya Perla <sathya.perla@broadcom.com>
 M:     Ajit Khaparde <ajit.khaparde@broadcom.com>
 M:     Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
 M:     Somnath Kotur <somnath.kotur@broadcom.com>
@@ -7738,7 +7736,7 @@ Hyper-V CORE AND DRIVERS
 M:     "K. Y. Srinivasan" <kys@microsoft.com>
 M:     Haiyang Zhang <haiyangz@microsoft.com>
 M:     Stephen Hemminger <sthemmin@microsoft.com>
-M:     Sasha Levin <sashal@kernel.org>
+M:     Wei Liu <wei.liu@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
 L:     linux-hyperv@vger.kernel.org
 S:     Supported
@@ -10164,7 +10162,7 @@ MAXBOTIX ULTRASONIC RANGER IIO DRIVER
 M:     Andreas Klinger <ak@it-klinger.de>
 L:     linux-iio@vger.kernel.org
 S:     Maintained
-F:     Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.txt
+F:     Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml
 F:     drivers/iio/proximity/mb1232.c
 
 MAXIM MAX77650 PMIC MFD DRIVER
@@ -10467,7 +10465,7 @@ M:      Hugues Fruchet <hugues.fruchet@st.com>
 L:     linux-media@vger.kernel.org
 T:     git git://linuxtv.org/media_tree.git
 S:     Supported
-F:     Documentation/devicetree/bindings/media/st,stm32-dcmi.txt
+F:     Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
 F:     drivers/media/platform/stm32/stm32-dcmi.c
 
 MEDIA DRIVERS FOR NVIDIA TEGRA - VDE
@@ -11115,14 +11113,12 @@ S:    Maintained
 F:     drivers/usb/image/microtek.*
 
 MIPS
-M:     Ralf Baechle <ralf@linux-mips.org>
-M:     Paul Burton <paulburton@kernel.org>
+M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
-Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
-S:     Supported
+Q:     https://patchwork.kernel.org/project/linux-mips/list/
+S:     Maintained
 F:     Documentation/devicetree/bindings/mips/
 F:     Documentation/mips/
 F:     arch/mips/
@@ -12741,7 +12737,7 @@ M:      Tom Joseph <tjoseph@cadence.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/cdns,*.txt
-F:     drivers/pci/controller/pcie-cadence*
+F:     drivers/pci/controller/cadence/
 
 PCI DRIVER FOR FREESCALE LAYERSCAPE
 M:     Minghuan Lian <minghuan.Lian@nxp.com>
@@ -12954,7 +12950,6 @@ M:      Robert Richter <rrichter@marvell.com>
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
-F:     Documentation/devicetree/bindings/pci/pci-thunder-*
 F:     drivers/pci/controller/pci-thunder-*
 
 PCIE DRIVER FOR HISILICON
@@ -14229,7 +14224,7 @@ F:      include/dt-bindings/reset/
 F:     include/linux/reset.h
 F:     include/linux/reset/
 F:     include/linux/reset-controller.h
-K:      \b(?:devm_|of_)?reset_control(?:ler_[a-z]+|_[a-z_]+)?\b
+K:     \b(?:devm_|of_)?reset_control(?:ler_[a-z]+|_[a-z_]+)?\b
 
 RESTARTABLE SEQUENCES SUPPORT
 M:     Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
@@ -15924,7 +15919,7 @@ F:      drivers/*/stm32-*timer*
 F:     drivers/pwm/pwm-stm32*
 F:     include/linux/*/stm32-*tim*
 F:     Documentation/ABI/testing/*timer-stm32
-F:     Documentation/devicetree/bindings/*/stm32-*timer*
+F:     Documentation/devicetree/bindings/*/*stm32-*timer*
 F:     Documentation/devicetree/bindings/pwm/pwm-stm32*
 
 STMMAC ETHERNET DRIVER
@@ -16083,6 +16078,8 @@ SYNOPSYS DESIGNWARE 8250 UART DRIVER
 R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 S:     Maintained
 F:     drivers/tty/serial/8250/8250_dw.c
+F:     drivers/tty/serial/8250/8250_dwlib.*
+F:     drivers/tty/serial/8250/8250_lpss.c
 
 SYNOPSYS DESIGNWARE APB GPIO DRIVER
 M:     Hoan Tran <hoan@os.amperecomputing.com>
index 0914049..e25db57 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -68,6 +68,7 @@ unexport GREP_OPTIONS
 #
 # If KBUILD_VERBOSE equals 0 then the above command will be hidden.
 # If KBUILD_VERBOSE equals 1 then the above command is displayed.
+# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
 #
 # To put more focus on warnings, be less verbose as default
 # Use 'make V=1' to see the full commands
@@ -1238,7 +1239,7 @@ ifneq ($(dtstree),)
 %.dtb: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
 
-PHONY += dtbs dtbs_install dt_binding_check
+PHONY += dtbs dtbs_install dtbs_check
 dtbs dtbs_check: include/config/kernel.release scripts_dtc
        $(Q)$(MAKE) $(build)=$(dtstree)
 
@@ -1258,6 +1259,7 @@ PHONY += scripts_dtc
 scripts_dtc: scripts_basic
        $(Q)$(MAKE) $(build)=scripts/dtc
 
+PHONY += dt_binding_check
 dt_binding_check: scripts_dtc
        $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings
 
index 98de654..17fe351 100644 (file)
@@ -738,8 +738,9 @@ config HAVE_STACK_VALIDATION
 config HAVE_RELIABLE_STACKTRACE
        bool
        help
-         Architecture has a save_stack_trace_tsk_reliable() function which
-         only returns a stack trace if it can guarantee the trace is reliable.
+         Architecture has either save_stack_trace_tsk_reliable() or
+         arch_stack_walk_reliable() function which only returns a stack trace
+         if it can guarantee the trace is reliable.
 
 config HAVE_ARCH_HASH
        bool
index f3ced6d..9f66f96 100644 (file)
         * Supply voltage supervisor on board will not allow opp50 so
         * disable it and set opp100 as suspend OPP.
         */
-       opp50@300000000 {
+       opp50-300000000 {
                status = "disabled";
        };
 
-       opp100@600000000 {
+       opp100-600000000 {
                opp-suspend;
        };
 };
index 1b5a835..efea891 100644 (file)
@@ -21,6 +21,7 @@
 
        aliases {
                ethernet0 = &genet;
+               pcie0 = &pcie0;
        };
 
        leds {
@@ -31,6 +32,8 @@
                pwr {
                        label = "PWR";
                        gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+                       linux,default-trigger = "default-on";
                };
        };
 
index 66ab35e..28be033 100644 (file)
@@ -26,6 +26,8 @@
                pwr {
                        label = "PWR";
                        gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+                       linux,default-trigger = "default-on";
                };
        };
 };
index 74ed6d0..3734314 100644 (file)
@@ -27,6 +27,8 @@
                pwr {
                        label = "PWR";
                        gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+                       linux,default-trigger = "default-on";
                };
        };
 
index de7f85e..af06a55 100644 (file)
                regulator-max-microvolt = <1800000>;
        };
 
-       evm_3v3: fixedregulator-evm3v3 {
+       vsys_3v3: fixedregulator-vsys3v3 {
                /* Output of Cntlr A of TPS43351-Q1 on dra7-evm */
                compatible = "regulator-fixed";
-               regulator-name = "evm_3v3";
+               regulator-name = "vsys_3v3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                vin-supply = <&evm_12v0>;
index fc41883..2119a78 100644 (file)
                                clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER13_CLKCTRL 24>;
                                clock-names = "fck";
                                interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
                        };
                };
 
                                clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER14_CLKCTRL 24>;
                                clock-names = "fck";
                                interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
                        };
                };
 
                                clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>;
                                clock-names = "fck";
                                interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
                        };
                };
 
                                clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>;
                                clock-names = "fck";
                                interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
                        };
                };
 
index d78b684..4305051 100644 (file)
                                device_type = "pci";
                                ranges = <0x81000000 0 0          0x03000 0 0x00010000
                                          0x82000000 0 0x20013000 0x13000 0 0xffed000>;
+                               dma-ranges = <0x02000000 0x0 0x00000000 0x00000000 0x1 0x00000000>;
                                bus-range = <0x00 0xff>;
                                #interrupt-cells = <1>;
                                num-lanes = <1>;
                                device_type = "pci";
                                ranges = <0x81000000 0 0          0x03000 0 0x00010000
                                          0x82000000 0 0x30013000 0x13000 0 0xffed000>;
+                               dma-ranges = <0x02000000 0x0 0x00000000 0x00000000 0x1 0x00000000>;
                                bus-range = <0x00 0xff>;
                                #interrupt-cells = <1>;
                                num-lanes = <1>;
index 2f7539a..42b8a20 100644 (file)
 &usb4_tm {
        status = "disabled";
 };
+
+&mmc3 {
+       /* dra76x is not affected by i887 */
+       max-frequency = <96000000>;
+};
index 55cef4c..dc0a93b 100644 (file)
                clock-div = <1>;
        };
 
-       ipu1_gfclk_mux: ipu1_gfclk_mux@520 {
-               #clock-cells = <0>;
-               compatible = "ti,mux-clock";
-               clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>;
-               ti,bit-shift = <24>;
-               reg = <0x0520>;
-               assigned-clocks = <&ipu1_gfclk_mux>;
-               assigned-clock-parents = <&dpll_core_h22x2_ck>;
-       };
-
        dummy_ck: dummy_ck {
                #clock-cells = <0>;
                compatible = "fixed-clock";
                        compatible = "ti,clkctrl";
                        reg = <0x20 0x4>;
                        #clock-cells = <2>;
+                       assigned-clocks = <&ipu1_clkctrl DRA7_IPU1_MMU_IPU1_CLKCTRL 24>;
+                       assigned-clock-parents = <&dpll_core_h22x2_ck>;
                };
 
                ipu_clkctrl: ipu-clkctrl@50 {
index cd07562..84fcc20 100644 (file)
 
        /* SRAM on Colibri nEXT_CS0 */
        sram@0,0 {
-               compatible = "cypress,cy7c1019dv33-10zsximtd-ram";
+               compatible = "cypress,cy7c1019dv33-10zsxi", "mtd-ram";
                reg = <0 0 0x00010000>;
                #address-cells = <1>;
                #size-cells = <1>;
 
        /* SRAM on Colibri nEXT_CS1 */
        sram@1,0 {
-               compatible = "cypress,cy7c1019dv33-10zsximtd-ram";
+               compatible = "cypress,cy7c1019dv33-10zsxi", "mtd-ram";
                reg = <1 0 0x00010000>;
                #address-cells = <1>;
                #size-cells = <1>;
index 978dc1c..4d18952 100644 (file)
        pinctrl-0 = <&pinctrl_usdhc4>;
        bus-width = <8>;
        non-removable;
-       vmmc-supply = <&vdd_emmc_1p8>;
        status = "disabled";
 };
 
index d05be3f..04717cf 100644 (file)
        assigned-clock-rates = <400000000>;
        bus-width = <8>;
        fsl,tuning-step = <2>;
-       max-frequency = <100000000>;
        vmmc-supply = <&reg_module_3v3>;
        vqmmc-supply = <&reg_DCDC3>;
        non-removable;
index 92f6d0c..4c22828 100644 (file)
@@ -44,7 +44,7 @@
                        opp-hz = /bits/ 64 <792000000>;
                        opp-microvolt = <1000000>;
                        clock-latency-ns = <150000>;
-                       opp-supported-hw = <0xd>, <0xf>;
+                       opp-supported-hw = <0xd>, <0x7>;
                        opp-suspend;
                };
 
@@ -52,7 +52,7 @@
                        opp-hz = /bits/ 64 <996000000>;
                        opp-microvolt = <1100000>;
                        clock-latency-ns = <150000>;
-                       opp-supported-hw = <0xc>, <0xf>;
+                       opp-supported-hw = <0xc>, <0x7>;
                        opp-suspend;
                };
 
@@ -60,7 +60,7 @@
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1225000>;
                        clock-latency-ns = <150000>;
-                       opp-supported-hw = <0x8>, <0xf>;
+                       opp-supported-hw = <0x8>, <0x3>;
                        opp-suspend;
                };
        };
index 0855b1f..760a68c 100644 (file)
                };
 
                mdio0: mdio@2d24000 {
-                       compatible = "fsl,etsec2-mdio";
+                       compatible = "gianfar";
                        device_type = "mdio";
                        #address-cells = <1>;
                        #size-cells = <0>;
                };
 
                mdio1: mdio@2d64000 {
-                       compatible = "fsl,etsec2-mdio";
+                       compatible = "gianfar";
                        device_type = "mdio";
                        #address-cells = <1>;
                        #size-cells = <0>;
index 8566550..b6e82b1 100644 (file)
                pwm-names = "enable", "direction";
                direction-duty-cycle-ns = <10000000>;
        };
+
+       backlight: backlight {
+               compatible = "led-backlight";
+
+               leds = <&backlight_led>;
+               brightness-levels = <31 63 95 127 159 191 223 255>;
+               default-brightness-level = <6>;
+       };
 };
 
 &dss {
                vddi-supply = <&lcd_regulator>;
                reset-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;      /* gpio101 */
 
+               backlight = <&backlight>;
+
                width-mm = <50>;
                height-mm = <89>;
 
                ramp-up-us = <1024>;
                ramp-down-us = <8193>;
 
-               led@0 {
+               backlight_led: led@0 {
                        reg = <0>;
                        led-sources = <2>;
                        ti,led-mode = <0>;
                        label = ":backlight";
-                       linux,default-trigger = "backlight";
                };
 
                led@1 {
index beb9885..c0999e2 100644 (file)
        };
 
        sata: sata@fc600000 {
-               compatible = "renesas,sata-r8a7779", "renesas,rcar-sata";
+               compatible = "renesas,sata-r8a7779";
                reg = <0xfc600000 0x200000>;
                interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp1_clks R8A7779_CLK_SATA>;
index 519ff58..0afcae9 100644 (file)
@@ -178,6 +178,7 @@ CONFIG_SCHED_TRACER=y
 CONFIG_STACK_TRACER=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_TEST_KSTRTOX=y
+CONFIG_DEBUG_FS=y
 CONFIG_KGDB=y
 CONFIG_KGDB_KDB=y
 CONFIG_STRICT_DEVMEM=y
index c32c338..847f987 100644 (file)
@@ -375,6 +375,7 @@ CONFIG_BACKLIGHT_GENERIC=m
 CONFIG_BACKLIGHT_PWM=m
 CONFIG_BACKLIGHT_PANDORA=m
 CONFIG_BACKLIGHT_GPIO=m
+CONFIG_BACKLIGHT_LED=m
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
index fe2e1e8..e73c97b 100644 (file)
@@ -157,6 +157,7 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_FUNCTION_TRACER=y
index c3314b2..a827b4d 100644 (file)
@@ -392,9 +392,6 @@ static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu) {}
 static inline void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu) {}
 
-static inline void kvm_arm_vhe_guest_enter(void) {}
-static inline void kvm_arm_vhe_guest_exit(void) {}
-
 #define KVM_BP_HARDEN_UNKNOWN          -1
 #define KVM_BP_HARDEN_WA_NEEDED                0
 #define KVM_BP_HARDEN_NOT_REQUIRED     1
index 35ff620..03506ce 100644 (file)
@@ -91,6 +91,8 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
 obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
 endif
+AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6) += resume-imx6.o
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
 obj-$(CONFIG_SOC_IMX1) += mach-imx1.o
index 912aece..5aa5796 100644 (file)
@@ -109,17 +109,17 @@ void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_SUSPEND
-void v7_cpu_resume(void);
 void imx53_suspend(void __iomem *ocram_vbase);
 extern const u32 imx53_suspend_sz;
 void imx6_suspend(void __iomem *ocram_vbase);
 #else
-static inline void v7_cpu_resume(void) {}
 static inline void imx53_suspend(void __iomem *ocram_vbase) {}
 static const u32 imx53_suspend_sz;
 static inline void imx6_suspend(void __iomem *ocram_vbase) {}
 #endif
 
+void v7_cpu_resume(void);
+
 void imx6_pm_ccm_init(const char *ccm_compat);
 void imx6q_pm_init(void);
 void imx6dl_pm_init(void);
diff --git a/arch/arm/mach-imx/resume-imx6.S b/arch/arm/mach-imx/resume-imx6.S
new file mode 100644 (file)
index 0000000..5bd1ba7
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "hardware.h"
+
+/*
+ * The following code must assume it is running from physical address
+ * where absolute virtual addresses to the data section have to be
+ * turned into relative ones.
+ */
+
+ENTRY(v7_cpu_resume)
+       bl      v7_invalidate_l1
+#ifdef CONFIG_CACHE_L2X0
+       bl      l2c310_early_resume
+#endif
+       b       cpu_resume
+ENDPROC(v7_cpu_resume)
index 062391f..1eabf2d 100644 (file)
@@ -327,17 +327,3 @@ resume:
 
        ret     lr
 ENDPROC(imx6_suspend)
-
-/*
- * The following code must assume it is running from physical address
- * where absolute virtual addresses to the data section have to be
- * turned into relative ones.
- */
-
-ENTRY(v7_cpu_resume)
-       bl      v7_invalidate_l1
-#ifdef CONFIG_CACHE_L2X0
-       bl      l2c310_early_resume
-#endif
-       b       cpu_resume
-ENDPROC(v7_cpu_resume)
index 01f0f4b..75034fe 100644 (file)
@@ -9,7 +9,6 @@ menuconfig ARCH_MESON
        select CACHE_L2X0
        select PINCTRL
        select PINCTRL_MESON
-       select COMMON_CLK
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
 
index e1135b9..5017a3b 100644 (file)
@@ -16,7 +16,7 @@ hwmod-common                          = omap_hwmod.o omap_hwmod_reset.o \
 clock-common                           = clock.o
 secure-common                          = omap-smc.o omap-secure.o
 
-obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
 obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common)
 obj-$(CONFIG_SOC_AM33XX) += $(hwmod-common) $(secure-common)
index f280472..27608d1 100644 (file)
@@ -431,7 +431,6 @@ void __init omap2420_init_early(void)
        omap_hwmod_init_postsetup();
        omap_clk_soc_init = omap2420_dt_clk_init;
        rate_table = omap2420_rate_table;
-       omap_secure_init();
 }
 
 void __init omap2420_init_late(void)
@@ -456,7 +455,6 @@ void __init omap2430_init_early(void)
        omap_hwmod_init_postsetup();
        omap_clk_soc_init = omap2430_dt_clk_init;
        rate_table = omap2430_rate_table;
-       omap_secure_init();
 }
 
 void __init omap2430_init_late(void)
index f82f25c..d5dc128 100644 (file)
        #size-cells = <0>;
 
        bus-width = <4>;
-       max-frequency = <50000000>;
+       max-frequency = <60000000>;
 
        non-removable;
        disable-wp;
index a8bb3fa..cb1b48f 100644 (file)
                compatible = "brcm,bcm43438-bt";
                interrupt-parent = <&gpio_intc>;
                interrupts = <95 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "host-wakeup";
                shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
                max-speed = <2000000>;
                clocks = <&wifi32k>;
index 6082ae0..d237162 100644 (file)
@@ -20,6 +20,8 @@
 };
 
 &fman0 {
+       fsl,erratum-a050385;
+
        /* these aliases provide the FMan ports mapping */
        enet0: ethernet@e0000 {
        };
index d3d26cc..13460a3 100644 (file)
                        compatible = "ethernet-phy-ieee802.3-c22";
                        reg = <0>;
                };
-
-               ethphy1: ethernet-phy@1 {
-                       compatible = "ethernet-phy-ieee802.3-c22";
-                       reg = <1>;
-               };
        };
 };
 
index e1d357e..d8c44d3 100644 (file)
                };
 
                gmac0: ethernet@ff800000 {
-                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
                        reg = <0xff800000 0x2000>;
                        interrupts = <0 90 4>;
                        interrupt-names = "macirq";
                };
 
                gmac1: ethernet@ff802000 {
-                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
                        reg = <0xff802000 0x2000>;
                        interrupts = <0 91 4>;
                        interrupt-names = "macirq";
                };
 
                gmac2: ethernet@ff804000 {
-                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+                       compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
                        reg = <0xff804000 0x2000>;
                        interrupts = <0 92 4>;
                        interrupt-names = "macirq";
index 905109f..4db223d 100644 (file)
@@ -773,7 +773,7 @@ CONFIG_ARCH_R8A774A1=y
 CONFIG_ARCH_R8A774B1=y
 CONFIG_ARCH_R8A774C0=y
 CONFIG_ARCH_R8A7795=y
-CONFIG_ARCH_R8A7796=y
+CONFIG_ARCH_R8A77960=y
 CONFIG_ARCH_R8A77961=y
 CONFIG_ARCH_R8A77965=y
 CONFIG_ARCH_R8A77970=y
index 25fec4b..a358e97 100644 (file)
@@ -32,7 +32,7 @@ static inline void gic_write_eoir(u32 irq)
        isb();
 }
 
-static inline void gic_write_dir(u32 irq)
+static __always_inline void gic_write_dir(u32 irq)
 {
        write_sysreg_s(irq, SYS_ICC_DIR_EL1);
        isb();
index 806e9dc..a4d1b5f 100644 (file)
@@ -69,7 +69,7 @@ static inline int icache_is_aliasing(void)
        return test_bit(ICACHEF_ALIASING, &__icache_flags);
 }
 
-static inline int icache_is_vpipt(void)
+static __always_inline int icache_is_vpipt(void)
 {
        return test_bit(ICACHEF_VPIPT, &__icache_flags);
 }
index 665c78e..e6cca3d 100644 (file)
@@ -145,7 +145,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static inline void __flush_icache_all(void)
+static __always_inline void __flush_icache_all(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
                return;
index 92ef953..2a746b9 100644 (file)
@@ -435,13 +435,13 @@ cpuid_feature_extract_signed_field(u64 features, int field)
        return cpuid_feature_extract_signed_field_width(features, field, 4);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
 {
        return (u64)(features << (64 - width - field)) >> (64 - width);
 }
 
-static inline unsigned int __attribute_const__
+static __always_inline unsigned int __attribute_const__
 cpuid_feature_extract_unsigned_field(u64 features, int field)
 {
        return cpuid_feature_extract_unsigned_field_width(features, field, 4);
@@ -564,7 +564,7 @@ static inline bool system_supports_mixed_endian(void)
        return val == 0x1;
 }
 
-static inline bool system_supports_fpsimd(void)
+static __always_inline bool system_supports_fpsimd(void)
 {
        return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
 }
@@ -575,13 +575,13 @@ static inline bool system_uses_ttbr0_pan(void)
                !cpus_have_const_cap(ARM64_HAS_PAN);
 }
 
-static inline bool system_supports_sve(void)
+static __always_inline bool system_supports_sve(void)
 {
        return IS_ENABLED(CONFIG_ARM64_SVE) &&
                cpus_have_const_cap(ARM64_SVE);
 }
 
-static inline bool system_supports_cnp(void)
+static __always_inline bool system_supports_cnp(void)
 {
        return IS_ENABLED(CONFIG_ARM64_CNP) &&
                cpus_have_const_cap(ARM64_HAS_CNP);
index 4e531f5..6facd13 100644 (file)
@@ -34,7 +34,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 }
 
 #define __raw_writel __raw_writel
-static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+static __always_inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
        asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
 }
@@ -69,7 +69,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 }
 
 #define __raw_readl __raw_readl
-static inline u32 __raw_readl(const volatile void __iomem *addr)
+static __always_inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        u32 val;
        asm volatile(ALTERNATIVE("ldr %w0, [%1]",
index 688c634..f658dda 100644 (file)
@@ -36,7 +36,7 @@ void kvm_inject_undef32(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
 
-static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
 {
        return !(vcpu->arch.hcr_el2 & HCR_RW);
 }
@@ -127,7 +127,7 @@ static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
        vcpu->arch.vsesr_el2 = vsesr;
 }
 
-static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
 }
@@ -153,17 +153,17 @@ static inline void vcpu_write_elr_el1(const struct kvm_vcpu *vcpu, unsigned long
                *__vcpu_elr_el1(vcpu) = v;
 }
 
-static inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
 {
        return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pstate;
 }
 
-static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
 }
 
-static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
 {
        if (vcpu_mode_is_32bit(vcpu))
                return kvm_condition_valid32(vcpu);
@@ -181,13 +181,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
  * coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
  * AArch32 with banked registers.
  */
-static inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
+static __always_inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
                                         u8 reg_num)
 {
        return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs.regs[reg_num];
 }
 
-static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
+static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
                                unsigned long val)
 {
        if (reg_num != 31)
@@ -264,12 +264,12 @@ static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
        return mode != PSR_MODE_EL0t;
 }
 
-static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
+static __always_inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.esr_el2;
 }
 
-static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
 
@@ -279,12 +279,12 @@ static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
        return -1;
 }
 
-static inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.fault.far_el2;
 }
 
-static inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
+static __always_inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
 {
        return ((phys_addr_t)vcpu->arch.fault.hpfar_el2 & HPFAR_MASK) << 8;
 }
@@ -299,7 +299,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_xVC_IMM_MASK;
 }
 
-static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
 }
@@ -319,17 +319,17 @@ static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF);
 }
 
-static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
        return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
 }
 
-static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
 }
 
-static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) ||
                kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
@@ -340,18 +340,18 @@ static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
 }
 
-static inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
+static __always_inline unsigned int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
 {
        return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT);
 }
 
 /* This one is not specific to Data Abort */
-static inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_trap_il_is32bit(const struct kvm_vcpu *vcpu)
 {
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_IL);
 }
 
-static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 {
        return ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
 }
@@ -361,17 +361,17 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC;
 }
 
-static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
+static __always_inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
-static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
 {
        switch (kvm_vcpu_trap_get_fault(vcpu)) {
        case FSC_SEA:
@@ -390,7 +390,7 @@ static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu)
        }
 }
 
-static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
 {
        u32 esr = kvm_vcpu_get_hsr(vcpu);
        return ESR_ELx_SYS64_ISS_RT(esr);
@@ -504,7 +504,7 @@ static inline unsigned long vcpu_data_host_to_guest(struct kvm_vcpu *vcpu,
        return data;            /* Leave LE untouched */
 }
 
-static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
+static __always_inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
 {
        if (vcpu_mode_is_32bit(vcpu))
                kvm_skip_instr32(vcpu, is_wide_instr);
@@ -519,7 +519,7 @@ static inline void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
  * Skip an instruction which has been emulated at hyp while most guest sysregs
  * are live.
  */
-static inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
+static __always_inline void __hyp_text __kvm_skip_instr(struct kvm_vcpu *vcpu)
 {
        *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
        vcpu->arch.ctxt.gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR);
index d87aa60..57fd46a 100644 (file)
@@ -626,38 +626,6 @@ static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
 static inline void kvm_clr_pmu_events(u32 clr) {}
 #endif
 
-static inline void kvm_arm_vhe_guest_enter(void)
-{
-       local_daif_mask();
-
-       /*
-        * Having IRQs masked via PMR when entering the guest means the GIC
-        * will not signal the CPU of interrupts of lower priority, and the
-        * only way to get out will be via guest exceptions.
-        * Naturally, we want to avoid this.
-        *
-        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
-        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
-        */
-       pmr_sync();
-}
-
-static inline void kvm_arm_vhe_guest_exit(void)
-{
-       /*
-        * local_daif_restore() takes care to properly restore PSTATE.DAIF
-        * and the GIC PMR if the host is using IRQ priorities.
-        */
-       local_daif_restore(DAIF_PROCCTX_NOIRQ);
-
-       /*
-        * When we exit from the guest we change a number of CPU configuration
-        * parameters, such as traps.  Make sure these changes take effect
-        * before running the host or additional guests.
-        */
-       isb();
-}
-
 #define KVM_BP_HARDEN_UNKNOWN          -1
 #define KVM_BP_HARDEN_WA_NEEDED                0
 #define KVM_BP_HARDEN_NOT_REQUIRED     1
index a3a6a2b..fe57f60 100644 (file)
 #define read_sysreg_el2(r)     read_sysreg_elx(r, _EL2, _EL1)
 #define write_sysreg_el2(v,r)  write_sysreg_elx(v, r, _EL2, _EL1)
 
+/*
+ * Without an __arch_swab32(), we fall back to ___constant_swab32(), but the
+ * static inline can allow the compiler to out-of-line this. KVM always wants
+ * the macro version as its always inlined.
+ */
+#define __kvm_swab32(x)        ___constant_swab32(x)
+
 int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
index 53d846f..7857628 100644 (file)
@@ -93,7 +93,7 @@ void kvm_update_va_mask(struct alt_instr *alt,
                        __le32 *origptr, __le32 *updptr, int nr_inst);
 void kvm_compute_layout(void);
 
-static inline unsigned long __kern_hyp_va(unsigned long v)
+static __always_inline unsigned long __kern_hyp_va(unsigned long v)
 {
        asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
                                    "ror %0, %0, #1\n"
@@ -473,6 +473,7 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
 extern void *__kvm_bp_vect_base;
 extern int __kvm_harden_el2_vector_slot;
 
+/*  This is only called on a VHE system */
 static inline void *kvm_get_hyp_vector(void)
 {
        struct bp_hardening_data *data = arm64_get_bp_hardening_data();
index 0958ed6..61fd267 100644 (file)
@@ -83,7 +83,7 @@ static inline bool is_kernel_in_hyp_mode(void)
        return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
-static inline bool has_vhe(void)
+static __always_inline bool has_vhe(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
                return true;
index dfe8dd1..925086b 100644 (file)
@@ -625,7 +625,7 @@ static void __hyp_text __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
 }
 
 /* Switch to the guest for VHE systems running in EL2 */
-int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpu_context *host_ctxt;
        struct kvm_cpu_context *guest_ctxt;
@@ -678,7 +678,42 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
-NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
+NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe);
+
+int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
+{
+       int ret;
+
+       local_daif_mask();
+
+       /*
+        * Having IRQs masked via PMR when entering the guest means the GIC
+        * will not signal the CPU of interrupts of lower priority, and the
+        * only way to get out will be via guest exceptions.
+        * Naturally, we want to avoid this.
+        *
+        * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
+        * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
+        */
+       pmr_sync();
+
+       ret = __kvm_vcpu_run_vhe(vcpu);
+
+       /*
+        * local_daif_restore() takes care to properly restore PSTATE.DAIF
+        * and the GIC PMR if the host is using IRQ priorities.
+        */
+       local_daif_restore(DAIF_PROCCTX_NOIRQ);
+
+       /*
+        * When we exit from the guest we change a number of CPU configuration
+        * parameters, such as traps.  Make sure these changes take effect
+        * before running the host or additional guests.
+        */
+       isb();
+
+       return ret;
+}
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
index 29ee1fe..4f3a087 100644 (file)
@@ -69,14 +69,14 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
                u32 data = vcpu_get_reg(vcpu, rd);
                if (__is_be(vcpu)) {
                        /* guest pre-swabbed data, undo this for writel() */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                writel_relaxed(data, addr);
        } else {
                u32 data = readl_relaxed(addr);
                if (__is_be(vcpu)) {
                        /* guest expects swabbed data */
-                       data = swab32(data);
+                       data = __kvm_swab32(data);
                }
                vcpu_set_reg(vcpu, rd, data);
        }
index 8ef73e8..d89bb22 100644 (file)
@@ -260,14 +260,26 @@ asmlinkage void post_ttbr_update_workaround(void)
                        CONFIG_CAVIUM_ERRATUM_27456));
 }
 
-static int asids_init(void)
+static int asids_update_limit(void)
 {
-       asid_bits = get_cpu_asid_bits();
+       unsigned long num_available_asids = NUM_USER_ASIDS;
+
+       if (arm64_kernel_unmapped_at_el0())
+               num_available_asids /= 2;
        /*
         * Expect allocation after rollover to fail if we don't have at least
         * one more ASID than CPUs. ASID #0 is reserved for init_mm.
         */
-       WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
+       WARN_ON(num_available_asids - 1 <= num_possible_cpus());
+       pr_info("ASID allocator initialised with %lu entries\n",
+               num_available_asids);
+       return 0;
+}
+arch_initcall(asids_update_limit);
+
+static int asids_init(void)
+{
+       asid_bits = get_cpu_asid_bits();
        atomic64_set(&asid_generation, ASID_FIRST_VERSION);
        asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map),
                           GFP_KERNEL);
@@ -282,8 +294,6 @@ static int asids_init(void)
         */
        if (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
                set_kpti_asid_bits();
-
-       pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
        return 0;
 }
 early_initcall(asids_init);
index 37b9316..c340f94 100644 (file)
@@ -4,6 +4,8 @@
 #include "jz4780.dtsi"
 #include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/regulator/active-semi,8865-regulator.h>
 
 / {
        compatible = "img,ci20", "ingenic,jz4780";
 
                regulators {
                        vddcore: SUDCDC1 {
-                               regulator-name = "VDDCORE";
+                               regulator-name = "DCDC_REG1";
                                regulator-min-microvolt = <1100000>;
                                regulator-max-microvolt = <1100000>;
                                regulator-always-on;
                        };
                        vddmem: SUDCDC2 {
-                               regulator-name = "VDDMEM";
+                               regulator-name = "DCDC_REG2";
                                regulator-min-microvolt = <1500000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                        };
                        vcc_33: SUDCDC3 {
-                               regulator-name = "VCC33";
+                               regulator-name = "DCDC_REG3";
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-always-on;
                        };
                        vcc_50: SUDCDC4 {
-                               regulator-name = "VCC50";
+                               regulator-name = "SUDCDC_REG4";
                                regulator-min-microvolt = <5000000>;
                                regulator-max-microvolt = <5000000>;
                                regulator-always-on;
                        };
                        vcc_25: LDO_REG5 {
-                               regulator-name = "VCC25";
+                               regulator-name = "LDO_REG5";
                                regulator-min-microvolt = <2500000>;
                                regulator-max-microvolt = <2500000>;
                                regulator-always-on;
                        };
                        wifi_io: LDO_REG6 {
-                               regulator-name = "WIFIIO";
+                               regulator-name = "LDO_REG6";
                                regulator-min-microvolt = <2500000>;
                                regulator-max-microvolt = <2500000>;
                                regulator-always-on;
                        };
                        vcc_28: LDO_REG7 {
-                               regulator-name = "VCC28";
+                               regulator-name = "LDO_REG7";
                                regulator-min-microvolt = <2800000>;
                                regulator-max-microvolt = <2800000>;
                                regulator-always-on;
                        };
                        vcc_15: LDO_REG8 {
-                               regulator-name = "VCC15";
+                               regulator-name = "LDO_REG8";
                                regulator-min-microvolt = <1500000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                        };
-                       vcc_18: LDO_REG9 {
-                               regulator-name = "VCC18";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <1800000>;
+                       vrtc_18: LDO_REG9 {
+                               regulator-name = "LDO_REG9";
+                               /* Despite the datasheet stating 3.3V
+                                * for REG9 and the driver expecting that,
+                                * REG9 outputs 1.8V.
+                                * Likely the CI20 uses a proprietary
+                                * factory programmed chip variant.
+                                * Since this is a simple on/off LDO the
+                                * exact values do not matter.
+                                */
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-always-on;
                        };
                        vcc_11: LDO_REG10 {
-                               regulator-name = "VCC11";
-                               regulator-min-microvolt = <1100000>;
-                               regulator-max-microvolt = <1100000>;
+                               regulator-name = "LDO_REG10";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
                                regulator-always-on;
                        };
                };
                rtc@51 {
                        compatible = "nxp,pcf8563";
                        reg = <0x51>;
-                       interrupts = <110>;
+
+                       interrupt-parent = <&gpf>;
+                       interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
                };
 };
 
index 5accda2..a3301ba 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 
 / {
        #address-cells = <1>;
                #clock-cells = <1>;
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4740-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4740_CLK_RTC>;
-               clock-names = "rtc";
-       };
-
        tcu: timer@10002000 {
                compatible = "ingenic,jz4740-tcu", "simple-mfd";
                reg = <0x10002000 0x1000>;
 
                interrupt-parent = <&intc>;
                interrupts = <23 22 21>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4740-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
index f928329..bb89653 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/jz4780-cgu.h>
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/dma/jz4780-dma.h>
 
 / {
 
                interrupt-parent = <&intc>;
                interrupts = <27 26 25>;
+
+               watchdog: watchdog@0 {
+                       compatible = "ingenic,jz4780-watchdog";
+                       reg = <0x0 0xc>;
+
+                       clocks = <&tcu TCU_CLK_WDT>;
+                       clock-names = "wdt";
+               };
        };
 
        rtc_dev: rtc@10003000 {
                status = "disabled";
        };
 
-       watchdog: watchdog@10002000 {
-               compatible = "ingenic,jz4780-watchdog";
-               reg = <0x10002000 0x10>;
-
-               clocks = <&cgu JZ4780_CLK_RTCLK>;
-               clock-names = "rtc";
-       };
-
        nemc: nemc@13410000 {
                compatible = "ingenic,jz4780-nemc";
                reg = <0x13410000 0x10000>;
index 4994c69..147f7d5 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <dt-bindings/clock/ingenic,tcu.h>
 #include <dt-bindings/clock/x1000-cgu.h>
 #include <dt-bindings/dma/x1000-dma.h>
 
@@ -72,7 +73,7 @@
                        compatible = "ingenic,x1000-watchdog", "ingenic,jz4780-watchdog";
                        reg = <0x0 0x10>;
 
-                       clocks = <&cgu X1000_CLK_RTCLK>;
+                       clocks = <&tcu TCU_CLK_WDT>;
                        clock-names = "wdt";
                };
        };
        i2c0: i2c-controller@10050000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10050000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c1: i2c-controller@10051000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10051000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
        i2c2: i2c-controller@10052000 {
                compatible = "ingenic,x1000-i2c";
                reg = <0x10052000 0x1000>;
-
                #address-cells = <1>;
                #size-cells = <0>;
 
index 7c6a109..aabd097 100644 (file)
  * effective barrier as noted by commit 6b07d38aaa52 ("MIPS: Octeon: Use
  * optimized memory barrier primitives."). Here we specify that the affected
  * sync instructions should be emitted twice.
+ * Note that this expression is evaluated by the assembler (not the compiler),
+ * and that the assembler evaluates '==' as 0 or -1, not 0 or 1.
  */
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
-# define __SYNC_rpt(type)      (1 + (type == __SYNC_wmb))
+# define __SYNC_rpt(type)      (1 - (type == __SYNC_wmb))
 #else
 # define __SYNC_rpt(type)      1
 #endif
index 1ac2752..a7b469d 100644 (file)
@@ -605,7 +605,8 @@ static void __init bootcmdline_init(char **cmdline_p)
         * If we're configured to take boot arguments from DT, look for those
         * now.
         */
-       if (IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB))
+       if (IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB) ||
+           IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND))
                of_scan_flat_dt(bootcmdline_scan_chosen, &dt_bootargs);
 #endif
 
index 6176b9a..d0d832a 100644 (file)
@@ -134,7 +134,7 @@ void release_vpe(struct vpe *v)
 {
        list_del(&v->list);
        if (v->load_addr)
-               release_progmem(v);
+               release_progmem(v->load_addr);
        kfree(v);
 }
 
index aa89a41..d7fe840 100644 (file)
@@ -33,6 +33,7 @@ endif
 cflags-vdso := $(ccflags-vdso) \
        $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
        -O3 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+       -mrelax-pic-calls $(call cc-option, -mexplicit-relocs) \
        -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
        $(call cc-option, -fno-asynchronous-unwind-tables) \
        $(call cc-option, -fno-stack-protector)
@@ -51,6 +52,8 @@ endif
 
 CFLAGS_REMOVE_vgettimeofday.o = -pg
 
+DISABLE_VDSO := n
+
 #
 # For the pre-R6 code in arch/mips/vdso/vdso.h for locating
 # the base address of VDSO, the linker will emit a R_MIPS_PC32
@@ -64,11 +67,24 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
 ifndef CONFIG_CPU_MIPSR6
   ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
     $(warning MIPS VDSO requires binutils >= 2.25)
-    obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
-    ccflags-vdso += -DDISABLE_MIPS_VDSO
+    DISABLE_VDSO := y
   endif
 endif
 
+#
+# GCC (at least up to version 9.2) appears to emit function calls that make use
+# of the GOT when targeting microMIPS, which we can't use in the VDSO due to
+# the lack of relocations. As such, we disable the VDSO for microMIPS builds.
+#
+ifdef CONFIG_CPU_MICROMIPS
+  DISABLE_VDSO := y
+endif
+
+ifeq ($(DISABLE_VDSO),y)
+  obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
+  ccflags-vdso += -DDISABLE_MIPS_VDSO
+endif
+
 # VDSO linker flags.
 VDSO_LDFLAGS := \
        -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1 \
@@ -81,12 +97,18 @@ GCOV_PROFILE := n
 UBSAN_SANITIZE := n
 KCOV_INSTRUMENT := n
 
+# Check that we don't have PIC 'jalr t9' calls left
+quiet_cmd_vdso_mips_check = VDSOCHK $@
+      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
+                      then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
+                            rm -f $@; /bin/false); fi
+
 #
 # Shared build commands.
 #
 
 quiet_cmd_vdsold_and_vdso_check = LD      $@
-      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check)
+      cmd_vdsold_and_vdso_check = $(cmd_vdsold); $(cmd_vdso_check); $(cmd_vdso_mips_check)
 
 quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
index e745abc..245be4f 100644 (file)
@@ -2193,11 +2193,13 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset,
                 * oprofile_cpu_type already has a value, then we are
                 * possibly overriding a real PVR with a logical one,
                 * and, in that case, keep the current value for
-                * oprofile_cpu_type.
+                * oprofile_cpu_type. Futhermore, let's ensure that the
+                * fix for the PMAO bug is enabled on compatibility mode.
                 */
                if (old.oprofile_cpu_type != NULL) {
                        t->oprofile_cpu_type = old.oprofile_cpu_type;
                        t->oprofile_type = old.oprofile_type;
+                       t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG;
                }
        }
 
index 2462cd7..d085432 100644 (file)
@@ -331,11 +331,13 @@ int hw_breakpoint_handler(struct die_args *args)
        }
 
        info->type &= ~HW_BRK_TYPE_EXTRANEOUS_IRQ;
-       if (!dar_within_range(regs->dar, info))
-               info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
-
-       if (!IS_ENABLED(CONFIG_PPC_8xx) && !stepping_handler(regs, bp, info))
-               goto out;
+       if (IS_ENABLED(CONFIG_PPC_8xx)) {
+               if (!dar_within_range(regs->dar, info))
+                       info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
+       } else {
+               if (!stepping_handler(regs, bp, info))
+                       goto out;
+       }
 
        /*
         * As a policy, the callback is invoked in a 'trigger-after-execute'
index b4c89a1..a32d478 100644 (file)
@@ -303,6 +303,12 @@ SECTIONS
                *(.branch_lt)
        }
 
+#ifdef CONFIG_DEBUG_INFO_BTF
+       .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) {
+               *(.BTF)
+       }
+#endif
+
        .opd : AT(ADDR(.opd) - LOAD_OFFSET) {
                __start_opd = .;
                KEEP(*(.opd))
index ef7b111..1c07d5a 100644 (file)
@@ -373,7 +373,9 @@ static inline bool flush_coherent_icache(unsigned long addr)
         */
        if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) {
                mb(); /* sync */
+               allow_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
                icbi((void *)addr);
+               prevent_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
                mb(); /* sync */
                isync();
                return true;
index 73f029e..1a3b5a5 100644 (file)
@@ -121,6 +121,7 @@ config ARCH_FLATMEM_ENABLE
 
 config ARCH_SPARSEMEM_ENABLE
        def_bool y
+       depends on MMU
        select SPARSEMEM_VMEMMAP_ENABLE
 
 config ARCH_SELECT_MEMORY_MODEL
index d325b67..3078b2d 100644 (file)
@@ -10,4 +10,28 @@ config SOC_SIFIVE
        help
          This enables support for SiFive SoC platform hardware.
 
+config SOC_VIRT
+       bool "QEMU Virt Machine"
+       select VIRTIO_PCI
+       select VIRTIO_BALLOON
+       select VIRTIO_MMIO
+       select VIRTIO_CONSOLE
+       select VIRTIO_NET
+       select NET_9P_VIRTIO
+       select VIRTIO_BLK
+       select SCSI_VIRTIO
+       select DRM_VIRTIO_GPU
+       select HW_RANDOM_VIRTIO
+       select RPMSG_CHAR
+       select RPMSG_VIRTIO
+       select CRYPTO_DEV_VIRTIO
+       select VIRTIO_INPUT
+       select POWER_RESET_SYSCON
+       select POWER_RESET_SYSCON_POWEROFF
+       select GOLDFISH
+       select RTC_DRV_GOLDFISH
+       select SIFIVE_PLIC
+       help
+         This enables support for QEMU Virt Machine.
+
 endmenu
index b9009a2..259cb53 100644 (file)
@@ -13,8 +13,10 @@ LDFLAGS_vmlinux :=
 ifeq ($(CONFIG_DYNAMIC_FTRACE),y)
        LDFLAGS_vmlinux := --no-relax
 endif
-KBUILD_AFLAGS_MODULE += -fPIC
-KBUILD_CFLAGS_MODULE += -fPIC
+
+ifeq ($(CONFIG_64BIT)$(CONFIG_CMODEL_MEDLOW),yy)
+KBUILD_CFLAGS_MODULE += -mcmodel=medany
+endif
 
 export BITS
 ifeq ($(CONFIG_ARCH_RV64I),y)
index 8dab0bb..8a45a37 100644 (file)
@@ -1,2 +1,4 @@
 Image
 Image.gz
+loader
+loader.lds
index 609198c..4a2729f 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2018-2019 SiFive, Inc */
 
 #include "fu540-c000.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 /* Clock frequency (in Hz) of the PCB crystal for rtcclk */
 #define RTCCLK_FREQ            1000000
                clock-frequency = <RTCCLK_FREQ>;
                clock-output-names = "rtcclk";
        };
+       gpio-restart {
+               compatible = "gpio-restart";
+               gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+       };
 };
 
 &uart0 {
index e2ff95c..c8f0842 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_SOC_SIFIVE=y
+CONFIG_SOC_VIRT=y
 CONFIG_SMP=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -30,7 +31,6 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETLINK_DIAG=y
 CONFIG_NET_9P=y
-CONFIG_NET_9P_VIRTIO=y
 CONFIG_PCI=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_HOST_GENERIC=y
@@ -38,15 +38,12 @@ CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_SCSI_VIRTIO=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_NETDEVICES=y
-CONFIG_VIRTIO_NET=y
 CONFIG_MACB=y
 CONFIG_E1000E=y
 CONFIG_R8169=y
@@ -57,15 +54,13 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
-CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_SPI=y
 CONFIG_SPI_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
+CONFIG_POWER_RESET=y
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
-CONFIG_DRM_VIRTIO_GPU=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
@@ -78,12 +73,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
 CONFIG_MMC=y
 CONFIG_MMC_SPI=y
-CONFIG_VIRTIO_PCI=y
-CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_INPUT=y
-CONFIG_VIRTIO_MMIO=y
-CONFIG_RPMSG_CHAR=y
-CONFIG_RPMSG_VIRTIO=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -98,7 +88,6 @@ CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_9P_FS=y
 CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_PAGEALLOC=y
index eb51940..a844920 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_BPF_SYSCALL=y
+CONFIG_SOC_VIRT=y
 CONFIG_ARCH_RV32I=y
 CONFIG_SMP=y
 CONFIG_MODULES=y
@@ -30,7 +31,6 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETLINK_DIAG=y
 CONFIG_NET_9P=y
-CONFIG_NET_9P_VIRTIO=y
 CONFIG_PCI=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_HOST_GENERIC=y
@@ -38,15 +38,12 @@ CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_SCSI_VIRTIO=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_NETDEVICES=y
-CONFIG_VIRTIO_NET=y
 CONFIG_MACB=y
 CONFIG_E1000E=y
 CONFIG_R8169=y
@@ -57,13 +54,11 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
 CONFIG_HVC_RISCV_SBI=y
-CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_VIRTIO=y
 # CONFIG_PTP_1588_CLOCK is not set
+CONFIG_POWER_RESET=y
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
-CONFIG_DRM_VIRTIO_GPU=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
@@ -74,13 +69,7 @@ CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
-CONFIG_VIRTIO_PCI=y
-CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_INPUT=y
-CONFIG_VIRTIO_MMIO=y
-CONFIG_RPMSG_CHAR=y
-CONFIG_RPMSG_VIRTIO=y
-CONFIG_SIFIVE_PLIC=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -95,7 +84,6 @@ CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_9P_FS=y
 CONFIG_CRYPTO_USER_API_HASH=y
-CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_PAGEALLOC=y
index 435b655..8e18d2c 100644 (file)
 #define EXC_LOAD_PAGE_FAULT    13
 #define EXC_STORE_PAGE_FAULT   15
 
+/* PMP configuration */
+#define PMP_R                  0x01
+#define PMP_W                  0x02
+#define PMP_X                  0x04
+#define PMP_A                  0x18
+#define PMP_A_TOR              0x08
+#define PMP_A_NA4              0x10
+#define PMP_A_NAPOT            0x18
+#define PMP_L                  0x80
+
 /* symbolic CSR names: */
 #define CSR_CYCLE              0xc00
 #define CSR_TIME               0xc01
 #define CSR_MCAUSE             0x342
 #define CSR_MTVAL              0x343
 #define CSR_MIP                        0x344
+#define CSR_PMPCFG0            0x3a0
+#define CSR_PMPADDR0           0x3b0
 #define CSR_MHARTID            0xf14
 
 #ifdef CONFIG_RISCV_M_MODE
index 42347d0..49350c8 100644 (file)
@@ -28,13 +28,6 @@ static inline int syscall_get_nr(struct task_struct *task,
        return regs->a7;
 }
 
-static inline void syscall_set_nr(struct task_struct *task,
-                                 struct pt_regs *regs,
-                                 int sysno)
-{
-       regs->a7 = sysno;
-}
-
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
index bad4d85..208702d 100644 (file)
@@ -229,19 +229,12 @@ check_syscall_nr:
        li t0, __NR_syscalls
        la s0, sys_ni_syscall
        /*
-        * The tracer can change syscall number to valid/invalid value.
-        * We use syscall_set_nr helper in syscall_trace_enter thus we
-        * cannot trust the current value in a7 and have to reload from
-        * the current task pt_regs.
-        */
-       REG_L a7, PT_A7(sp)
-       /*
         * Syscall number held in a7.
         * If syscall number is above allowed value, redirect to ni_syscall.
         */
        bge a7, t0, 1f
        /*
-        * Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1.
+        * Check if syscall is rejected by tracer, i.e., a7 == -1.
         * If yes, we pretend it was executed.
         */
        li t1, -1
@@ -334,6 +327,7 @@ work_resched:
 handle_syscall_trace_enter:
        move a0, sp
        call do_syscall_trace_enter
+       move t0, a0
        REG_L a0, PT_A0(sp)
        REG_L a1, PT_A1(sp)
        REG_L a2, PT_A2(sp)
@@ -342,6 +336,7 @@ handle_syscall_trace_enter:
        REG_L a5, PT_A5(sp)
        REG_L a6, PT_A6(sp)
        REG_L a7, PT_A7(sp)
+       bnez t0, ret_from_syscall_rejected
        j check_syscall_nr
 handle_syscall_trace_exit:
        move a0, sp
index 271860f..85f2073 100644 (file)
@@ -58,6 +58,12 @@ _start_kernel:
        /* Reset all registers except ra, a0, a1 */
        call reset_regs
 
+       /* Setup a PMP to permit access to all of memory. */
+       li a0, -1
+       csrw CSR_PMPADDR0, a0
+       li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
+       csrw CSR_PMPCFG0, a0
+
        /*
         * The hartid in a0 is expected later on, and we have no firmware
         * to hand it to us.
index b740185..8bbe5db 100644 (file)
@@ -8,6 +8,10 @@
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+#include <linux/sizes.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
 
 static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
 {
@@ -386,3 +390,15 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
 
        return 0;
 }
+
+#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
+#define VMALLOC_MODULE_START \
+        max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START)
+void *module_alloc(unsigned long size)
+{
+       return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START,
+                                   VMALLOC_END, GFP_KERNEL,
+                                   PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+                                   __builtin_return_address(0));
+}
+#endif
index 4074642..444dc7b 100644 (file)
@@ -148,21 +148,19 @@ long arch_ptrace(struct task_struct *child, long request,
  * Allows PTRACE_SYSCALL to work.  These are called from entry.S in
  * {handle,ret_from}_syscall.
  */
-__visible void do_syscall_trace_enter(struct pt_regs *regs)
+__visible int do_syscall_trace_enter(struct pt_regs *regs)
 {
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                if (tracehook_report_syscall_entry(regs))
-                       syscall_set_nr(current, regs, -1);
+                       return -1;
 
        /*
         * Do the secure computing after ptrace; failures should be fast.
         * If this fails we might have return value in a0 from seccomp
         * (via SECCOMP_RET_ERRNO/TRACE).
         */
-       if (secure_computing() == -1) {
-               syscall_set_nr(current, regs, -1);
-               return;
-       }
+       if (secure_computing() == -1)
+               return -1;
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
@@ -170,6 +168,7 @@ __visible void do_syscall_trace_enter(struct pt_regs *regs)
 #endif
 
        audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
+       return 0;
 }
 
 __visible void do_syscall_trace_exit(struct pt_regs *regs)
index f4cad51..ffb3d94 100644 (file)
@@ -156,6 +156,6 @@ void __init trap_init(void)
        csr_write(CSR_SCRATCH, 0);
        /* Set the exception vector address */
        csr_write(CSR_TVEC, &handle_exception);
-       /* Enable all interrupts */
-       csr_write(CSR_IE, -1);
+       /* Enable interrupts */
+       csr_write(CSR_IE, IE_SIE | IE_EIE);
 }
index 965a8cf..fab8559 100644 (file)
@@ -131,7 +131,7 @@ void __init setup_bootmem(void)
        for_each_memblock(memory, reg) {
                phys_addr_t end = reg->base + reg->size;
 
-               if (reg->base <= vmlinux_end && vmlinux_end <= end) {
+               if (reg->base <= vmlinux_start && vmlinux_end <= end) {
                        mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
 
                        /*
index f0cc860..ec0ca90 100644 (file)
@@ -19,18 +19,20 @@ asmlinkage void __init kasan_early_init(void)
        for (i = 0; i < PTRS_PER_PTE; ++i)
                set_pte(kasan_early_shadow_pte + i,
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       PAGE_KERNEL));
+                              PAGE_KERNEL));
 
        for (i = 0; i < PTRS_PER_PMD; ++i)
                set_pmd(kasan_early_shadow_pmd + i,
-                pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pmd(PFN_DOWN
+                               (__pa((uintptr_t) kasan_early_shadow_pte)),
+                               __pgprot(_PAGE_TABLE)));
 
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        /* init for swapper_pg_dir */
        pgd = pgd_offset_k(KASAN_SHADOW_START);
@@ -38,37 +40,43 @@ asmlinkage void __init kasan_early_init(void)
        for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
             i += PGDIR_SIZE, ++pgd)
                set_pgd(pgd,
-                pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
-                       __pgprot(_PAGE_TABLE)));
+                       pfn_pgd(PFN_DOWN
+                               (__pa(((uintptr_t) kasan_early_shadow_pmd))),
+                               __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
 }
 
 static void __init populate(void *start, void *end)
 {
-       unsigned long i;
+       unsigned long i, offset;
        unsigned long vaddr = (unsigned long)start & PAGE_MASK;
        unsigned long vend = PAGE_ALIGN((unsigned long)end);
        unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
+       unsigned long n_ptes =
+           ((n_pages + PTRS_PER_PTE) & -PTRS_PER_PTE) / PTRS_PER_PTE;
        unsigned long n_pmds =
-               (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 :
-                                               n_pages / PTRS_PER_PTE;
+           ((n_ptes + PTRS_PER_PMD) & -PTRS_PER_PMD) / PTRS_PER_PMD;
+
+       pte_t *pte =
+           memblock_alloc(n_ptes * PTRS_PER_PTE * sizeof(pte_t), PAGE_SIZE);
+       pmd_t *pmd =
+           memblock_alloc(n_pmds * PTRS_PER_PMD * sizeof(pmd_t), PAGE_SIZE);
        pgd_t *pgd = pgd_offset_k(vaddr);
-       pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
-       pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; i++) {
                phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
-
-               set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
+               set_pte(&pte[i], pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
        }
 
-       for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD)
-               set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))),
+       for (i = 0, offset = 0; i < n_ptes; i++, offset += PTRS_PER_PTE)
+               set_pmd(&pmd[i],
+                       pfn_pmd(PFN_DOWN(__pa(&pte[offset])),
                                __pgprot(_PAGE_TABLE)));
 
-       for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE)
-               set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))),
+       for (i = 0, offset = 0; i < n_pmds; i++, offset += PTRS_PER_PMD)
+               set_pgd(&pgd[i],
+                       pfn_pgd(PFN_DOWN(__pa(&pmd[offset])),
                                __pgprot(_PAGE_TABLE)));
 
        flush_tlb_all();
@@ -81,7 +89,8 @@ void __init kasan_init(void)
        unsigned long i;
 
        kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
-                       (void *)kasan_mem_to_shadow((void *)VMALLOC_END));
+                                   (void *)kasan_mem_to_shadow((void *)
+                                                               VMALLOC_END));
 
        for_each_memblock(memory, reg) {
                void *start = (void *)__va(reg->base);
@@ -90,14 +99,14 @@ void __init kasan_init(void)
                if (start >= end)
                        break;
 
-               populate(kasan_mem_to_shadow(start),
-                        kasan_mem_to_shadow(end));
+               populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end));
        };
 
        for (i = 0; i < PTRS_PER_PTE; i++)
                set_pte(&kasan_early_shadow_pte[i],
                        mk_pte(virt_to_page(kasan_early_shadow_page),
-                       __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED)));
+                              __pgprot(_PAGE_PRESENT | _PAGE_READ |
+                                       _PAGE_ACCESSED)));
 
        memset(kasan_early_shadow_page, 0, PAGE_SIZE);
        init_task.kasan_depth = 0;
index 137a392..6d7c3b7 100644 (file)
@@ -752,6 +752,12 @@ static inline int pmd_write(pmd_t pmd)
        return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0;
 }
 
+#define pud_write pud_write
+static inline int pud_write(pud_t pud)
+{
+       return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0;
+}
+
 static inline int pmd_dirty(pmd_t pmd)
 {
        return (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0;
index bc61ea1..60716d1 100644 (file)
@@ -424,7 +424,7 @@ static void zpci_map_resources(struct pci_dev *pdev)
 
                if (zpci_use_mio(zdev))
                        pdev->resource[i].start =
-                               (resource_size_t __force) zdev->bars[i].mio_wb;
+                               (resource_size_t __force) zdev->bars[i].mio_wt;
                else
                        pdev->resource[i].start = (resource_size_t __force)
                                pci_iomap_range_fh(pdev, i, 0, 0);
@@ -531,7 +531,7 @@ static int zpci_setup_bus_resources(struct zpci_dev *zdev,
                        flags |= IORESOURCE_MEM_64;
 
                if (zpci_use_mio(zdev))
-                       addr = (unsigned long) zdev->bars[i].mio_wb;
+                       addr = (unsigned long) zdev->bars[i].mio_wt;
                else
                        addr = ZPCI_ADDR(entry);
                size = 1UL << zdev->bars[i].size;
index 94df086..513a555 100644 (file)
@@ -194,9 +194,10 @@ avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
 avx512_instr :=$(call as-instr,vpmovm2b %k1$(comma)%zmm5,-DCONFIG_AS_AVX512=1)
 sha1_ni_instr :=$(call as-instr,sha1msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA1_NI=1)
 sha256_ni_instr :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA256_NI=1)
+adx_instr := $(call as-instr,adox %r10$(comma)%r10,-DCONFIG_AS_ADX=1)
 
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr) $(adx_instr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr) $(adx_instr)
 
 KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
 
index b69e00b..8c2e9ea 100644 (file)
@@ -11,6 +11,7 @@ avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\
 avx512_supported :=$(call as-instr,vpmovm2b %k1$(comma)%zmm5,yes,no)
 sha1_ni_supported :=$(call as-instr,sha1msg1 %xmm0$(comma)%xmm1,yes,no)
 sha256_ni_supported :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,yes,no)
+adx_supported := $(call as-instr,adox %r10$(comma)%r10,yes,no)
 
 obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o
 
@@ -39,7 +40,11 @@ obj-$(CONFIG_CRYPTO_AEGIS128_AESNI_SSE2) += aegis128-aesni.o
 
 obj-$(CONFIG_CRYPTO_NHPOLY1305_SSE2) += nhpoly1305-sse2.o
 obj-$(CONFIG_CRYPTO_NHPOLY1305_AVX2) += nhpoly1305-avx2.o
-obj-$(CONFIG_CRYPTO_CURVE25519_X86) += curve25519-x86_64.o
+
+# These modules require the assembler to support ADX.
+ifeq ($(adx_supported),yes)
+       obj-$(CONFIG_CRYPTO_CURVE25519_X86) += curve25519-x86_64.o
+endif
 
 # These modules require assembler to support AVX.
 ifeq ($(avx_supported),yes)
index 02c6ef8..07344d8 100644 (file)
@@ -19,7 +19,14 @@ struct task_struct;
 void io_bitmap_share(struct task_struct *tsk);
 void io_bitmap_exit(void);
 
-void tss_update_io_bitmap(void);
+void native_tss_update_io_bitmap(void);
+
+#ifdef CONFIG_PARAVIRT_XXL
+#include <asm/paravirt.h>
+#else
+#define tss_update_io_bitmap native_tss_update_io_bitmap
+#endif
+
 #else
 static inline void io_bitmap_share(struct task_struct *tsk) { }
 static inline void io_bitmap_exit(void) { }
index 03946eb..2a8f2bd 100644 (file)
@@ -292,6 +292,14 @@ enum x86emul_mode {
 #define X86EMUL_SMM_MASK             (1 << 6)
 #define X86EMUL_SMM_INSIDE_NMI_MASK  (1 << 7)
 
+/*
+ * fastop functions are declared as taking a never-defined fastop parameter,
+ * so they can't be called from C directly.
+ */
+struct fastop;
+
+typedef void (*fastop_t)(struct fastop *);
+
 struct x86_emulate_ctxt {
        const struct x86_emulate_ops *ops;
 
@@ -324,7 +332,10 @@ struct x86_emulate_ctxt {
        struct operand src;
        struct operand src2;
        struct operand dst;
-       int (*execute)(struct x86_emulate_ctxt *ctxt);
+       union {
+               int (*execute)(struct x86_emulate_ctxt *ctxt);
+               fastop_t fop;
+       };
        int (*check_perm)(struct x86_emulate_ctxt *ctxt);
        /*
         * The following six fields are cleared together,
index 40a0c0f..98959e8 100644 (file)
@@ -1122,6 +1122,7 @@ struct kvm_x86_ops {
        int (*handle_exit)(struct kvm_vcpu *vcpu,
                enum exit_fastpath_completion exit_fastpath);
        int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+       void (*update_emulated_instruction)(struct kvm_vcpu *vcpu);
        void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
        u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu);
        void (*patch_hypercall)(struct kvm_vcpu *vcpu,
@@ -1146,7 +1147,7 @@ struct kvm_x86_ops {
        void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
        void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
        void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
-       void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
+       int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
        int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
        int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
        int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
index 86e7317..694d8da 100644 (file)
@@ -295,6 +295,13 @@ static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
        PVOP_VCALL3(cpu.write_idt_entry, dt, entry, g);
 }
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+static inline void tss_update_io_bitmap(void)
+{
+       PVOP_VCALL0(cpu.update_io_bitmap);
+}
+#endif
+
 static inline void paravirt_activate_mm(struct mm_struct *prev,
                                        struct mm_struct *next)
 {
index 8481296..732f62e 100644 (file)
@@ -140,6 +140,10 @@ struct pv_cpu_ops {
 
        void (*load_sp0)(unsigned long sp0);
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       void (*update_io_bitmap)(void);
+#endif
+
        void (*wbinvd)(void);
 
        /* cpuid emulation, mostly so that caps bits can be disabled */
index 2a85287..8521af3 100644 (file)
@@ -72,7 +72,7 @@
 #define SECONDARY_EXEC_MODE_BASED_EPT_EXEC     VMCS_CONTROL_BIT(MODE_BASED_EPT_EXEC)
 #define SECONDARY_EXEC_PT_USE_GPA              VMCS_CONTROL_BIT(PT_USE_GPA)
 #define SECONDARY_EXEC_TSC_SCALING              VMCS_CONTROL_BIT(TSC_SCALING)
-#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   0x04000000
+#define SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE   VMCS_CONTROL_BIT(USR_WAIT_PAUSE)
 
 #define PIN_BASED_EXT_INTR_MASK                 VMCS_CONTROL_BIT(INTR_EXITING)
 #define PIN_BASED_NMI_EXITING                   VMCS_CONTROL_BIT(NMI_EXITING)
index a50e4a0..9915990 100644 (file)
@@ -81,6 +81,7 @@
 #define VMX_FEATURE_MODE_BASED_EPT_EXEC        ( 2*32+ 22) /* "ept_mode_based_exec" Enable separate EPT EXEC bits for supervisor vs. user */
 #define VMX_FEATURE_PT_USE_GPA         ( 2*32+ 24) /* "" Processor Trace logs GPAs */
 #define VMX_FEATURE_TSC_SCALING                ( 2*32+ 25) /* Scale hardware TSC when read in guest */
+#define VMX_FEATURE_USR_WAIT_PAUSE     ( 2*32+ 26) /* Enable TPAUSE, UMONITOR, UMWAIT in guest */
 #define VMX_FEATURE_ENCLV_EXITING      ( 2*32+ 28) /* "" VM-Exit on ENCLV (leaf dependent) */
 
 #endif /* _ASM_X86_VMXFEATURES_H */
index 503d3f4..3f3f780 100644 (file)
@@ -390,6 +390,7 @@ struct kvm_sync_regs {
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
+#define KVM_STATE_NESTED_MTF_PENDING   0x00000008
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
index 52c9bfb..4cdb123 100644 (file)
@@ -445,7 +445,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c)
         * cpuid bit to be set.  We need to ensure that we
         * update that bit in this CPU's "cpu_info".
         */
-       get_cpu_cap(c);
+       set_cpu_cap(c, X86_FEATURE_OSPKE);
 }
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
index d817f25..6efe041 100644 (file)
@@ -425,7 +425,29 @@ static void __init sev_map_percpu_data(void)
        }
 }
 
+static bool pv_tlb_flush_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+               kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
+static DEFINE_PER_CPU(cpumask_var_t, __pv_cpu_mask);
+
 #ifdef CONFIG_SMP
+
+static bool pv_ipi_supported(void)
+{
+       return kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI);
+}
+
+static bool pv_sched_yield_supported(void)
+{
+       return (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
+               !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
+           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME));
+}
+
 #define KVM_IPI_CLUSTER_SIZE   (2 * BITS_PER_LONG)
 
 static void __send_ipi_mask(const struct cpumask *mask, int vector)
@@ -490,12 +512,12 @@ static void kvm_send_ipi_mask(const struct cpumask *mask, int vector)
 static void kvm_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
 {
        unsigned int this_cpu = smp_processor_id();
-       struct cpumask new_mask;
+       struct cpumask *new_mask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
        const struct cpumask *local_mask;
 
-       cpumask_copy(&new_mask, mask);
-       cpumask_clear_cpu(this_cpu, &new_mask);
-       local_mask = &new_mask;
+       cpumask_copy(new_mask, mask);
+       cpumask_clear_cpu(this_cpu, new_mask);
+       local_mask = new_mask;
        __send_ipi_mask(local_mask, vector);
 }
 
@@ -575,7 +597,6 @@ static void __init kvm_apf_trap_init(void)
        update_intr_gate(X86_TRAP_PF, async_page_fault);
 }
 
-static DEFINE_PER_CPU(cpumask_var_t, __pv_tlb_mask);
 
 static void kvm_flush_tlb_others(const struct cpumask *cpumask,
                        const struct flush_tlb_info *info)
@@ -583,7 +604,7 @@ static void kvm_flush_tlb_others(const struct cpumask *cpumask,
        u8 state;
        int cpu;
        struct kvm_steal_time *src;
-       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_tlb_mask);
+       struct cpumask *flushmask = this_cpu_cpumask_var_ptr(__pv_cpu_mask);
 
        cpumask_copy(flushmask, cpumask);
        /*
@@ -619,11 +640,10 @@ static void __init kvm_guest_init(void)
                pv_ops.time.steal_clock = kvm_steal_clock;
        }
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported()) {
                pv_ops.mmu.flush_tlb_others = kvm_flush_tlb_others;
                pv_ops.mmu.tlb_remove_table = tlb_remove_table;
+               pr_info("KVM setup pv remote TLB flush\n");
        }
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
@@ -632,9 +652,7 @@ static void __init kvm_guest_init(void)
 #ifdef CONFIG_SMP
        smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
        smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SCHED_YIELD) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_sched_yield_supported()) {
                smp_ops.send_call_func_ipi = kvm_smp_send_call_func_ipi;
                pr_info("KVM setup pv sched yield\n");
        }
@@ -700,7 +718,7 @@ static uint32_t __init kvm_detect(void)
 static void __init kvm_apic_init(void)
 {
 #if defined(CONFIG_SMP)
-       if (kvm_para_has_feature(KVM_FEATURE_PV_SEND_IPI))
+       if (pv_ipi_supported())
                kvm_setup_pv_ipi();
 #endif
 }
@@ -732,26 +750,31 @@ static __init int activate_jump_labels(void)
 }
 arch_initcall(activate_jump_labels);
 
-static __init int kvm_setup_pv_tlb_flush(void)
+static __init int kvm_alloc_cpumask(void)
 {
        int cpu;
+       bool alloc = false;
 
        if (!kvm_para_available() || nopv)
                return 0;
 
-       if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+       if (pv_tlb_flush_supported())
+               alloc = true;
+
+#if defined(CONFIG_SMP)
+       if (pv_ipi_supported())
+               alloc = true;
+#endif
+
+       if (alloc)
                for_each_possible_cpu(cpu) {
-                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu),
+                       zalloc_cpumask_var_node(per_cpu_ptr(&__pv_cpu_mask, cpu),
                                GFP_KERNEL, cpu_to_node(cpu));
                }
-               pr_info("KVM setup pv remote TLB flush\n");
-       }
 
        return 0;
 }
-arch_initcall(kvm_setup_pv_tlb_flush);
+arch_initcall(kvm_alloc_cpumask);
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
 
index 789f5e4..c131ba4 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/timer.h>
 #include <asm/special_insns.h>
 #include <asm/tlb.h>
+#include <asm/io_bitmap.h>
 
 /*
  * nop stub, which must not clobber anything *including the stack* to
@@ -341,6 +342,10 @@ struct paravirt_patch_template pv_ops = {
        .cpu.iret               = native_iret,
        .cpu.swapgs             = native_swapgs,
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       .cpu.update_io_bitmap   = native_tss_update_io_bitmap,
+#endif
+
        .cpu.start_context_switch       = paravirt_nop,
        .cpu.end_context_switch         = paravirt_nop,
 
index 839b524..3053c85 100644 (file)
@@ -374,7 +374,7 @@ static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
 /**
  * tss_update_io_bitmap - Update I/O bitmap before exiting to usermode
  */
-void tss_update_io_bitmap(void)
+void native_tss_update_io_bitmap(void)
 {
        struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
        struct thread_struct *t = &current->thread;
index 991019d..1bb4927 100644 (file)
@@ -59,6 +59,19 @@ config KVM
 
          If unsure, say N.
 
+config KVM_WERROR
+       bool "Compile KVM with -Werror"
+       # KASAN may cause the build to fail due to larger frames
+       default y if X86_64 && !KASAN
+       # We use the dependency on !COMPILE_TEST to not be enabled
+       # blindly in allmodconfig or allyesconfig configurations
+       depends on (X86_64 && !KASAN) || !COMPILE_TEST
+       depends on EXPERT
+       help
+         Add -Werror to the build flags for (and only for) i915.ko.
+
+         If in doubt, say "N".
+
 config KVM_INTEL
        tristate "KVM for Intel (and compatible) processors support"
        depends on KVM && IA32_FEAT_CTL
index b19ef42..e553f0f 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 ccflags-y += -Iarch/x86/kvm
+ccflags-$(CONFIG_KVM_WERROR) += -Werror
 
 KVM := ../../../virt/kvm
 
index ddbc619..dd19fb3 100644 (file)
 #define NR_FASTOP (ilog2(sizeof(ulong)) + 1)
 #define FASTOP_SIZE 8
 
-/*
- * fastop functions have a special calling convention:
- *
- * dst:    rax        (in/out)
- * src:    rdx        (in/out)
- * src2:   rcx        (in)
- * flags:  rflags     (in/out)
- * ex:     rsi        (in:fastop pointer, out:zero if exception)
- *
- * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
- * different operand sizes can be reached by calculation, rather than a jump
- * table (which would be bigger than the code).
- *
- * fastop functions are declared as taking a never-defined fastop parameter,
- * so they can't be called from C directly.
- */
-
-struct fastop;
-
 struct opcode {
        u64 flags : 56;
        u64 intercept : 8;
@@ -311,8 +292,19 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 #define ON64(x)
 #endif
 
-typedef void (*fastop_t)(struct fastop *);
-
+/*
+ * fastop functions have a special calling convention:
+ *
+ * dst:    rax        (in/out)
+ * src:    rdx        (in/out)
+ * src2:   rcx        (in)
+ * flags:  rflags     (in/out)
+ * ex:     rsi        (in:fastop pointer, out:zero if exception)
+ *
+ * Moreover, they are all exactly FASTOP_SIZE bytes long, so functions for
+ * different operand sizes can be reached by calculation, rather than a jump
+ * table (which would be bigger than the code).
+ */
 static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop);
 
 #define __FOP_FUNC(name) \
@@ -5683,7 +5675,7 @@ special_insn:
 
        if (ctxt->execute) {
                if (ctxt->d & Fastop)
-                       rc = fastop(ctxt, (fastop_t)ctxt->execute);
+                       rc = fastop(ctxt, ctxt->fop);
                else
                        rc = ctxt->execute(ctxt);
                if (rc != X86EMUL_CONTINUE)
index 79afa0b..c47d2ac 100644 (file)
@@ -417,7 +417,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
 
                        kvm_set_msi_irq(vcpu->kvm, entry, &irq);
 
-                       if (irq.level &&
+                       if (irq.trig_mode &&
                            kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT,
                                                irq.dest_id, irq.dest_mode))
                                __set_bit(irq.vector, ioapic_handled_vectors);
index afcd30d..e3099c6 100644 (file)
@@ -627,9 +627,11 @@ static inline bool pv_eoi_enabled(struct kvm_vcpu *vcpu)
 static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
 {
        u8 val;
-       if (pv_eoi_get_user(vcpu, &val) < 0)
+       if (pv_eoi_get_user(vcpu, &val) < 0) {
                printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
                           (unsigned long long)vcpu->arch.pv_eoi.msr_val);
+               return false;
+       }
        return val & 0x1;
 }
 
@@ -1046,11 +1048,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                                                       apic->regs + APIC_TMR);
                }
 
-               if (vcpu->arch.apicv_active)
-                       kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
-               else {
+               if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) {
                        kvm_lapic_set_irr(vector, apic);
-
                        kvm_make_request(KVM_REQ_EVENT, vcpu);
                        kvm_vcpu_kick(vcpu);
                }
index 3c6522b..ffcd96f 100644 (file)
@@ -339,7 +339,7 @@ TRACE_EVENT(
                /* These depend on page entry type, so compute them now.  */
                __field(bool, r)
                __field(bool, x)
-               __field(u8, u)
+               __field(signed char, u)
        ),
 
        TP_fast_assign(
index bef0ba3..24c0b2b 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id svm_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_SVM),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
+#endif
 
 #define IOPM_ALLOC_ORDER 2
 #define MSRPM_ALLOC_ORDER 1
@@ -1005,33 +1007,32 @@ static void svm_cpu_uninit(int cpu)
 static int svm_cpu_init(int cpu)
 {
        struct svm_cpu_data *sd;
-       int r;
 
        sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
        if (!sd)
                return -ENOMEM;
        sd->cpu = cpu;
-       r = -ENOMEM;
        sd->save_area = alloc_page(GFP_KERNEL);
        if (!sd->save_area)
-               goto err_1;
+               goto free_cpu_data;
 
        if (svm_sev_enabled()) {
-               r = -ENOMEM;
                sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
                                              sizeof(void *),
                                              GFP_KERNEL);
                if (!sd->sev_vmcbs)
-                       goto err_1;
+                       goto free_save_area;
        }
 
        per_cpu(svm_data, cpu) = sd;
 
        return 0;
 
-err_1:
+free_save_area:
+       __free_page(sd->save_area);
+free_cpu_data:
        kfree(sd);
-       return r;
+       return -ENOMEM;
 
 }
 
@@ -1350,6 +1351,24 @@ static __init void svm_adjust_mmio_mask(void)
        kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
 }
 
+static void svm_hardware_teardown(void)
+{
+       int cpu;
+
+       if (svm_sev_enabled()) {
+               bitmap_free(sev_asid_bitmap);
+               bitmap_free(sev_reclaim_asid_bitmap);
+
+               sev_flush_asids();
+       }
+
+       for_each_possible_cpu(cpu)
+               svm_cpu_uninit(cpu);
+
+       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
+       iopm_base = 0;
+}
+
 static __init int svm_hardware_setup(void)
 {
        int cpu;
@@ -1463,29 +1482,10 @@ static __init int svm_hardware_setup(void)
        return 0;
 
 err:
-       __free_pages(iopm_pages, IOPM_ALLOC_ORDER);
-       iopm_base = 0;
+       svm_hardware_teardown();
        return r;
 }
 
-static __exit void svm_hardware_unsetup(void)
-{
-       int cpu;
-
-       if (svm_sev_enabled()) {
-               bitmap_free(sev_asid_bitmap);
-               bitmap_free(sev_reclaim_asid_bitmap);
-
-               sev_flush_asids();
-       }
-
-       for_each_possible_cpu(cpu)
-               svm_cpu_uninit(cpu);
-
-       __free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT), IOPM_ALLOC_ORDER);
-       iopm_base = 0;
-}
-
 static void init_seg(struct vmcb_seg *seg)
 {
        seg->selector = 0;
@@ -2196,8 +2196,9 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 static int avic_init_vcpu(struct vcpu_svm *svm)
 {
        int ret;
+       struct kvm_vcpu *vcpu = &svm->vcpu;
 
-       if (!kvm_vcpu_apicv_active(&svm->vcpu))
+       if (!avic || !irqchip_in_kernel(vcpu->kvm))
                return 0;
 
        ret = avic_init_backing_page(&svm->vcpu);
@@ -5232,6 +5233,9 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
        struct vmcb *vmcb = svm->vmcb;
        bool activated = kvm_vcpu_apicv_active(vcpu);
 
+       if (!avic)
+               return;
+
        if (activated) {
                /**
                 * During AVIC temporary deactivation, guest could update
@@ -5255,8 +5259,11 @@ static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
        return;
 }
 
-static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
+static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
 {
+       if (!vcpu->arch.apicv_active)
+               return -1;
+
        kvm_lapic_set_irr(vec, vcpu->arch.apic);
        smp_mb__after_atomic();
 
@@ -5268,6 +5275,8 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
                put_cpu();
        } else
                kvm_vcpu_wake_up(vcpu);
+
+       return 0;
 }
 
 static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
@@ -7378,7 +7387,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
        .hardware_setup = svm_hardware_setup,
-       .hardware_unsetup = svm_hardware_unsetup,
+       .hardware_unsetup = svm_hardware_teardown,
        .check_processor_compatibility = svm_check_processor_compat,
        .hardware_enable = svm_hardware_enable,
        .hardware_disable = svm_hardware_disable,
@@ -7433,6 +7442,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .run = svm_vcpu_run,
        .handle_exit = handle_exit,
        .skip_emulated_instruction = skip_emulated_instruction,
+       .update_emulated_instruction = NULL,
        .set_interrupt_shadow = svm_set_interrupt_shadow,
        .get_interrupt_shadow = svm_get_interrupt_shadow,
        .patch_hypercall = svm_patch_hypercall,
index 283bdb7..f486e26 100644 (file)
@@ -12,6 +12,7 @@ extern bool __read_mostly enable_ept;
 extern bool __read_mostly enable_unrestricted_guest;
 extern bool __read_mostly enable_ept_ad_bits;
 extern bool __read_mostly enable_pml;
+extern bool __read_mostly enable_apicv;
 extern int __read_mostly pt_mode;
 
 #define PT_MODE_SYSTEM         0
index 3589cd3..e920d78 100644 (file)
@@ -3161,10 +3161,10 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
  * or KVM_SET_NESTED_STATE).  Otherwise it's called from vmlaunch/vmresume.
  *
  * Returns:
- *     NVMX_ENTRY_SUCCESS: Entered VMX non-root mode
- *     NVMX_ENTRY_VMFAIL:  Consistency check VMFail
- *     NVMX_ENTRY_VMEXIT:  Consistency check VMExit
- *     NVMX_ENTRY_KVM_INTERNAL_ERROR: KVM internal error
+ *     NVMX_VMENTRY_SUCCESS: Entered VMX non-root mode
+ *     NVMX_VMENTRY_VMFAIL:  Consistency check VMFail
+ *     NVMX_VMENTRY_VMEXIT:  Consistency check VMExit
+ *     NVMX_VMENTRY_KVM_INTERNAL_ERROR: KVM internal error
  */
 enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
                                                        bool from_vmentry)
@@ -3609,8 +3609,15 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
        unsigned long exit_qual;
        bool block_nested_events =
            vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu);
+       bool mtf_pending = vmx->nested.mtf_pending;
        struct kvm_lapic *apic = vcpu->arch.apic;
 
+       /*
+        * Clear the MTF state. If a higher priority VM-exit is delivered first,
+        * this state is discarded.
+        */
+       vmx->nested.mtf_pending = false;
+
        if (lapic_in_kernel(vcpu) &&
                test_bit(KVM_APIC_INIT, &apic->pending_events)) {
                if (block_nested_events)
@@ -3621,8 +3628,28 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
                return 0;
        }
 
+       /*
+        * Process any exceptions that are not debug traps before MTF.
+        */
+       if (vcpu->arch.exception.pending &&
+           !vmx_pending_dbg_trap(vcpu) &&
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
+               return 0;
+       }
+
+       if (mtf_pending) {
+               if (block_nested_events)
+                       return -EBUSY;
+               nested_vmx_update_pending_dbg(vcpu);
+               nested_vmx_vmexit(vcpu, EXIT_REASON_MONITOR_TRAP_FLAG, 0, 0);
+               return 0;
+       }
+
        if (vcpu->arch.exception.pending &&
-               nested_vmx_check_exception(vcpu, &exit_qual)) {
+           nested_vmx_check_exception(vcpu, &exit_qual)) {
                if (block_nested_events)
                        return -EBUSY;
                nested_vmx_inject_exception_vmexit(vcpu, exit_qual);
@@ -5285,24 +5312,17 @@ fail:
        return 1;
 }
 
-
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-                                      struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size)
 {
-       unsigned long exit_qualification;
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        gpa_t bitmap, last_bitmap;
-       unsigned int port;
-       int size;
        u8 b;
 
-       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
-               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
-       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
-       port = exit_qualification >> 16;
-       size = (exit_qualification & 7) + 1;
-
        last_bitmap = (gpa_t)-1;
        b = -1;
 
@@ -5329,8 +5349,26 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
        return false;
 }
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+                                      struct vmcs12 *vmcs12)
+{
+       unsigned long exit_qualification;
+       unsigned short port;
+       int size;
+
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+       exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+       port = exit_qualification >> 16;
+       size = (exit_qualification & 7) + 1;
+
+       return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
- * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
+ * Return 1 if we should exit from L2 to L1 to handle an MSR access,
  * rather than handle it ourselves in L0. I.e., check whether L1 expressed
  * disinterest in the current event (read or write a specific MSR) by using an
  * MSR bitmap. This may be the case even when L0 doesn't use MSR bitmaps.
@@ -5712,6 +5750,9 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
 
                        if (vmx->nested.nested_run_pending)
                                kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
+
+                       if (vmx->nested.mtf_pending)
+                               kvm_state.flags |= KVM_STATE_NESTED_MTF_PENDING;
                }
        }
 
@@ -5892,6 +5933,9 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
        vmx->nested.nested_run_pending =
                !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
 
+       vmx->nested.mtf_pending =
+               !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING);
+
        ret = -EINVAL;
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
@@ -5949,8 +5993,7 @@ void nested_vmx_set_vmcs_shadowing_bitmap(void)
  * bit in the high half is on if the corresponding bit in the control field
  * may be on. See also vmx_control_verify().
  */
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv)
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 {
        /*
         * Note that as a general rule, the high half of the MSRs (bits in
@@ -5977,7 +6020,7 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
                PIN_BASED_EXT_INTR_MASK |
                PIN_BASED_NMI_EXITING |
                PIN_BASED_VIRTUAL_NMIS |
-               (apicv ? PIN_BASED_POSTED_INTR : 0);
+               (enable_apicv ? PIN_BASED_POSTED_INTR : 0);
        msrs->pinbased_ctls_high |=
                PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
                PIN_BASED_VMX_PREEMPTION_TIMER;
index fc874d4..9aeda46 100644 (file)
@@ -17,8 +17,7 @@ enum nvmx_vmentry_status {
 };
 
 void vmx_leave_nested(struct kvm_vcpu *vcpu);
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-                               bool apicv);
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
 void nested_vmx_hardware_unsetup(void);
 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
 void nested_vmx_set_vmcs_shadowing_bitmap(void);
@@ -34,6 +33,8 @@ int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
                        u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
 void nested_vmx_pmu_entry_exit_ctls_update(struct kvm_vcpu *vcpu);
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+                                int size);
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 {
@@ -175,6 +176,11 @@ static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
        return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
 }
 
+static inline int nested_cpu_has_mtf(struct vmcs12 *vmcs12)
+{
+       return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
+}
+
 static inline int nested_cpu_has_ept(struct vmcs12 *vmcs12)
 {
        return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_EPT);
index 3be25ec..40b1e61 100644 (file)
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+#ifdef MODULE
 static const struct x86_cpu_id vmx_cpu_id[] = {
        X86_FEATURE_MATCH(X86_FEATURE_VMX),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, vmx_cpu_id);
+#endif
 
 bool __read_mostly enable_vpid = 1;
 module_param_named(vpid, enable_vpid, bool, 0444);
@@ -95,7 +97,7 @@ module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv = 1;
+bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
@@ -1175,6 +1177,10 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
                                           vmx->guest_msrs[i].mask);
 
        }
+
+       if (vmx->nested.need_vmcs12_to_shadow_sync)
+               nested_sync_vmcs12_to_shadow(vcpu);
+
        if (vmx->guest_state_loaded)
                return;
 
@@ -1599,6 +1605,40 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+
+/*
+ * Recognizes a pending MTF VM-exit and records the nested state for later
+ * delivery.
+ */
+static void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+       if (!is_guest_mode(vcpu))
+               return;
+
+       /*
+        * Per the SDM, MTF takes priority over debug-trap exceptions besides
+        * T-bit traps. As instruction emulation is completed (i.e. at the
+        * instruction boundary), any #DB exception pending delivery must be a
+        * debug-trap. Record the pending MTF state to be delivered in
+        * vmx_check_nested_events().
+        */
+       if (nested_cpu_has_mtf(vmcs12) &&
+           (!vcpu->arch.exception.pending ||
+            vcpu->arch.exception.nr == DB_VECTOR))
+               vmx->nested.mtf_pending = true;
+       else
+               vmx->nested.mtf_pending = false;
+}
+
+static int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+       vmx_update_emulated_instruction(vcpu);
+       return skip_emulated_instruction(vcpu);
+}
+
 static void vmx_clear_hlt(struct kvm_vcpu *vcpu)
 {
        /*
@@ -3818,24 +3858,29 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu,
  * 2. If target vcpu isn't running(root mode), kick it to pick up the
  * interrupt from PIR in next vmentry.
  */
-static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
+static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        int r;
 
        r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
        if (!r)
-               return;
+               return 0;
+
+       if (!vcpu->arch.apicv_active)
+               return -1;
 
        if (pi_test_and_set_pir(vector, &vmx->pi_desc))
-               return;
+               return 0;
 
        /* If a previous notification has sent the IPI, nothing to do.  */
        if (pi_test_and_set_on(&vmx->pi_desc))
-               return;
+               return 0;
 
        if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
                kvm_vcpu_kick(vcpu);
+
+       return 0;
 }
 
 /*
@@ -6482,8 +6527,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                vmcs_write32(PLE_WINDOW, vmx->ple_window);
        }
 
-       if (vmx->nested.need_vmcs12_to_shadow_sync)
-               nested_sync_vmcs12_to_shadow(vcpu);
+       /*
+        * We did this in prepare_switch_to_guest, because it needs to
+        * be within srcu_read_lock.
+        */
+       WARN_ON_ONCE(vmx->nested.need_vmcs12_to_shadow_sync);
 
        if (kvm_register_is_dirty(vcpu, VCPU_REGS_RSP))
                vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
@@ -6757,8 +6805,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
 
        if (nested)
                nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
-                                          vmx_capability.ept,
-                                          kvm_vcpu_apicv_active(vcpu));
+                                          vmx_capability.ept);
        else
                memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
 
@@ -6839,8 +6886,7 @@ static int __init vmx_check_processor_compat(void)
        if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
                return -EIO;
        if (nested)
-               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept,
-                                          enable_apicv);
+               nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
        if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
                printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
                                smp_processor_id());
@@ -7101,6 +7147,40 @@ static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
        to_vmx(vcpu)->req_immediate_exit = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+                                 struct x86_instruction_info *info)
+{
+       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       unsigned short port;
+       bool intercept;
+       int size;
+
+       if (info->intercept == x86_intercept_in ||
+           info->intercept == x86_intercept_ins) {
+               port = info->src_val;
+               size = info->dst_bytes;
+       } else {
+               port = info->dst_val;
+               size = info->src_bytes;
+       }
+
+       /*
+        * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+        * VM-exits depend on the 'unconditional IO exiting' VM-execution
+        * control.
+        *
+        * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+        */
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               intercept = nested_cpu_has(vmcs12,
+                                          CPU_BASED_UNCOND_IO_EXITING);
+       else
+               intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+       /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+       return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
                               struct x86_instruction_info *info,
                               enum x86_intercept_stage stage)
@@ -7108,19 +7188,45 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
        struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+       switch (info->intercept) {
        /*
         * RDPID causes #UD if disabled through secondary execution controls.
         * Because it is marked as EmulateOnUD, we need to intercept it here.
         */
-       if (info->intercept == x86_intercept_rdtscp &&
-           !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
-               ctxt->exception.vector = UD_VECTOR;
-               ctxt->exception.error_code_valid = false;
-               return X86EMUL_PROPAGATE_FAULT;
-       }
+       case x86_intercept_rdtscp:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+                       ctxt->exception.vector = UD_VECTOR;
+                       ctxt->exception.error_code_valid = false;
+                       return X86EMUL_PROPAGATE_FAULT;
+               }
+               break;
+
+       case x86_intercept_in:
+       case x86_intercept_ins:
+       case x86_intercept_out:
+       case x86_intercept_outs:
+               return vmx_check_intercept_io(vcpu, info);
+
+       case x86_intercept_lgdt:
+       case x86_intercept_lidt:
+       case x86_intercept_lldt:
+       case x86_intercept_ltr:
+       case x86_intercept_sgdt:
+       case x86_intercept_sidt:
+       case x86_intercept_sldt:
+       case x86_intercept_str:
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
+                       return X86EMUL_CONTINUE;
+
+               /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+               break;
 
        /* TODO: check more intercepts... */
-       return X86EMUL_CONTINUE;
+       default:
+               break;
+       }
+
+       return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
@@ -7702,7 +7808,7 @@ static __init int hardware_setup(void)
 
        if (nested) {
                nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
-                                          vmx_capability.ept, enable_apicv);
+                                          vmx_capability.ept);
 
                r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);
                if (r)
@@ -7786,7 +7892,8 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
 
        .run = vmx_vcpu_run,
        .handle_exit = vmx_handle_exit,
-       .skip_emulated_instruction = skip_emulated_instruction,
+       .skip_emulated_instruction = vmx_skip_emulated_instruction,
+       .update_emulated_instruction = vmx_update_emulated_instruction,
        .set_interrupt_shadow = vmx_set_interrupt_shadow,
        .get_interrupt_shadow = vmx_get_interrupt_shadow,
        .patch_hypercall = vmx_patch_hypercall,
index 7f42cf3..e64da06 100644 (file)
@@ -150,6 +150,9 @@ struct nested_vmx {
        /* L2 must run next, and mustn't decide to exit to L1. */
        bool nested_run_pending;
 
+       /* Pending MTF VM-exit into L1.  */
+       bool mtf_pending;
+
        struct loaded_vmcs vmcs02;
 
        /*
index fb5d64e..5de2006 100644 (file)
@@ -6891,6 +6891,8 @@ restart:
                        kvm_rip_write(vcpu, ctxt->eip);
                        if (r && ctxt->tf)
                                r = kvm_vcpu_do_singlestep(vcpu);
+                       if (kvm_x86_ops->update_emulated_instruction)
+                               kvm_x86_ops->update_emulated_instruction(vcpu);
                        __kvm_set_rflags(vcpu, ctxt->eflags);
                }
 
@@ -7188,15 +7190,15 @@ static void kvm_timer_init(void)
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
 #ifdef CONFIG_CPU_FREQ
-               struct cpufreq_policy policy;
+               struct cpufreq_policy *policy;
                int cpu;
 
-               memset(&policy, 0, sizeof(policy));
                cpu = get_cpu();
-               cpufreq_get_policy(&policy, cpu);
-               if (policy.cpuinfo.max_freq)
-                       max_tsc_khz = policy.cpuinfo.max_freq;
+               policy = cpufreq_cpu_get(cpu);
+               if (policy && policy->cpuinfo.max_freq)
+                       max_tsc_khz = policy->cpuinfo.max_freq;
                put_cpu();
+               cpufreq_cpu_put(policy);
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -7306,12 +7308,12 @@ int kvm_arch_init(void *opaque)
        }
 
        if (!ops->cpu_has_kvm_support()) {
-               printk(KERN_ERR "kvm: no hardware support\n");
+               pr_err_ratelimited("kvm: no hardware support\n");
                r = -EOPNOTSUPP;
                goto out;
        }
        if (ops->disabled_by_bios()) {
-               printk(KERN_ERR "kvm: disabled by bios\n");
+               pr_err_ratelimited("kvm: disabled by bios\n");
                r = -EOPNOTSUPP;
                goto out;
        }
index 64229da..69309cd 100644 (file)
@@ -363,13 +363,8 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m,
 {
        const struct ptdump_range ptdump_ranges[] = {
 #ifdef CONFIG_X86_64
-
-#define normalize_addr_shift (64 - (__VIRTUAL_MASK_SHIFT + 1))
-#define normalize_addr(u) ((signed long)((u) << normalize_addr_shift) >> \
-                          normalize_addr_shift)
-
        {0, PTRS_PER_PGD * PGD_LEVEL_MULT / 2},
-       {normalize_addr(PTRS_PER_PGD * PGD_LEVEL_MULT / 2), ~0UL},
+       {GUARD_HOLE_END_ADDR, ~0UL},
 #else
        {0, ~0UL},
 #endif
index fa8506e..d19a2ed 100644 (file)
@@ -180,7 +180,7 @@ void efi_sync_low_kernel_mappings(void)
 static inline phys_addr_t
 virt_to_phys_or_null_size(void *va, unsigned long size)
 {
-       bool bad_size;
+       phys_addr_t pa;
 
        if (!va)
                return 0;
@@ -188,16 +188,13 @@ virt_to_phys_or_null_size(void *va, unsigned long size)
        if (virt_addr_valid(va))
                return virt_to_phys(va);
 
-       /*
-        * A fully aligned variable on the stack is guaranteed not to
-        * cross a page bounary. Try to catch strings on the stack by
-        * checking that 'size' is a power of two.
-        */
-       bad_size = size > PAGE_SIZE || !is_power_of_2(size);
+       pa = slow_virt_to_phys(va);
 
-       WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
+       /* check if the object crosses a page boundary */
+       if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
+               return 0;
 
-       return slow_virt_to_phys(va);
+       return pa;
 }
 
 #define virt_to_phys_or_null(addr)                             \
@@ -568,85 +565,25 @@ efi_thunk_set_virtual_address_map(unsigned long memory_map_size,
 
 static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-       efi_status_t status;
-       u32 phys_tm, phys_tc;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-       phys_tc = virt_to_phys_or_null(tc);
-
-       status = efi_thunk(get_time, phys_tm, phys_tc);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t efi_thunk_set_time(efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(set_time, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t
 efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
                          efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_enabled, phys_pending, phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_enabled = virt_to_phys_or_null(enabled);
-       phys_pending = virt_to_phys_or_null(pending);
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(get_wakeup_time, phys_enabled,
-                            phys_pending, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static efi_status_t
 efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 {
-       efi_status_t status;
-       u32 phys_tm;
-       unsigned long flags;
-
-       spin_lock(&rtc_lock);
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_tm = virt_to_phys_or_null(tm);
-
-       status = efi_thunk(set_wakeup_time, enabled, phys_tm);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-       spin_unlock(&rtc_lock);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static unsigned long efi_name_size(efi_char16_t *name)
@@ -658,6 +595,8 @@ static efi_status_t
 efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
                       u32 *attr, unsigned long *data_size, void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        efi_status_t status;
        u32 phys_name, phys_vendor, phys_attr;
        u32 phys_data_size, phys_data;
@@ -665,14 +604,19 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_data_size = virt_to_phys_or_null(data_size);
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
        phys_attr = virt_to_phys_or_null(attr);
        phys_data = virt_to_phys_or_null_size(data, *data_size);
 
-       status = efi_thunk(get_variable, phys_name, phys_vendor,
-                          phys_attr, phys_data_size, phys_data);
+       if (!phys_name || (data && !phys_data))
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(get_variable, phys_name, phys_vendor,
+                                  phys_attr, phys_data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -683,19 +627,25 @@ static efi_status_t
 efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
                       u32 attr, unsigned long data_size, void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        u32 phys_name, phys_vendor, phys_data;
        efi_status_t status;
        unsigned long flags;
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       /* If data_size is > sizeof(u32) we've got problems */
-       status = efi_thunk(set_variable, phys_name, phys_vendor,
-                          attr, data_size, phys_data);
+       if (!phys_name || !phys_data)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(set_variable, phys_name, phys_vendor,
+                                  attr, data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -707,6 +657,8 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
                                   u32 attr, unsigned long data_size,
                                   void *data)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        u32 phys_name, phys_vendor, phys_data;
        efi_status_t status;
        unsigned long flags;
@@ -714,13 +666,17 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
        if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
                return EFI_NOT_READY;
 
+       *vnd = *vendor;
+
        phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_data = virt_to_phys_or_null_size(data, data_size);
 
-       /* If data_size is > sizeof(u32) we've got problems */
-       status = efi_thunk(set_variable, phys_name, phys_vendor,
-                          attr, data_size, phys_data);
+       if (!phys_name || !phys_data)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(set_variable, phys_name, phys_vendor,
+                                  attr, data_size, phys_data);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -732,39 +688,36 @@ efi_thunk_get_next_variable(unsigned long *name_size,
                            efi_char16_t *name,
                            efi_guid_t *vendor)
 {
+       u8 buf[24] __aligned(8);
+       efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
        efi_status_t status;
        u32 phys_name_size, phys_name, phys_vendor;
        unsigned long flags;
 
        spin_lock_irqsave(&efi_runtime_lock, flags);
 
+       *vnd = *vendor;
+
        phys_name_size = virt_to_phys_or_null(name_size);
-       phys_vendor = virt_to_phys_or_null(vendor);
+       phys_vendor = virt_to_phys_or_null(vnd);
        phys_name = virt_to_phys_or_null_size(name, *name_size);
 
-       status = efi_thunk(get_next_variable, phys_name_size,
-                          phys_name, phys_vendor);
+       if (!phys_name)
+               status = EFI_INVALID_PARAMETER;
+       else
+               status = efi_thunk(get_next_variable, phys_name_size,
+                                  phys_name, phys_vendor);
 
        spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
+       *vendor = *vnd;
        return status;
 }
 
 static efi_status_t
 efi_thunk_get_next_high_mono_count(u32 *count)
 {
-       efi_status_t status;
-       u32 phys_count;
-       unsigned long flags;
-
-       spin_lock_irqsave(&efi_runtime_lock, flags);
-
-       phys_count = virt_to_phys_or_null(count);
-       status = efi_thunk(get_next_high_mono_count, phys_count);
-
-       spin_unlock_irqrestore(&efi_runtime_lock, flags);
-
-       return status;
+       return EFI_UNSUPPORTED;
 }
 
 static void
index 7940912..507f4fb 100644 (file)
@@ -72,6 +72,9 @@
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
 #include <asm/cpu.h>
+#ifdef CONFIG_X86_IOPL_IOPERM
+#include <asm/io_bitmap.h>
+#endif
 
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
@@ -837,6 +840,25 @@ static void xen_load_sp0(unsigned long sp0)
        this_cpu_write(cpu_tss_rw.x86_tss.sp0, sp0);
 }
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+static void xen_update_io_bitmap(void)
+{
+       struct physdev_set_iobitmap iobitmap;
+       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+
+       native_tss_update_io_bitmap();
+
+       iobitmap.bitmap = (uint8_t *)(&tss->x86_tss) +
+                         tss->x86_tss.io_bitmap_base;
+       if (tss->x86_tss.io_bitmap_base == IO_BITMAP_OFFSET_INVALID)
+               iobitmap.nr_ports = 0;
+       else
+               iobitmap.nr_ports = IO_BITMAP_BITS;
+
+       HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
+}
+#endif
+
 static void xen_io_delay(void)
 {
 }
@@ -1047,6 +1069,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .write_idt_entry = xen_write_idt_entry,
        .load_sp0 = xen_load_sp0,
 
+#ifdef CONFIG_X86_IOPL_IOPERM
+       .update_io_bitmap = xen_update_io_bitmap,
+#endif
        .io_delay = xen_io_delay,
 
        /* Xen takes care of %gs when switching to usermode for us */
index b5516b0..6e9ec6e 100644 (file)
@@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat)
 }
 #endif
 
+static bool acpi_no_watchdog;
+
 static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
 {
        const struct acpi_table_wdat *wdat = NULL;
        acpi_status status;
 
-       if (acpi_disabled)
+       if (acpi_disabled || acpi_no_watchdog)
                return NULL;
 
        status = acpi_get_table(ACPI_SIG_WDAT, 0,
@@ -88,6 +90,14 @@ bool acpi_has_watchdog(void)
 }
 EXPORT_SYMBOL_GPL(acpi_has_watchdog);
 
+/* ACPI watchdog can be disabled on boot command line */
+static int __init disable_acpi_watchdog(char *str)
+{
+       acpi_no_watchdog = true;
+       return 1;
+}
+__setup("acpi_no_watchdog", disable_acpi_watchdog);
+
 void __init acpi_watchdog_init(void)
 {
        const struct acpi_wdat_entry *entries;
@@ -126,12 +136,11 @@ void __init acpi_watchdog_init(void)
                gas = &entries[i].register_region;
 
                res.start = gas->address;
+               res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
                if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
                        res.flags = IORESOURCE_MEM;
-                       res.end = res.start + ALIGN(gas->access_width, 4) - 1;
                } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
                        res.flags = IORESOURCE_IO;
-                       res.end = res.start + gas->access_width - 1;
                } else {
                        pr_warn("Unsupported address space: %u\n",
                                gas->space_id);
index a6b2082..e47c8a4 100644 (file)
@@ -5228,6 +5228,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
                binder_dev = container_of(filp->private_data,
                                          struct binder_device, miscdev);
        }
+       refcount_inc(&binder_dev->ref);
        proc->context = &binder_dev->context;
        binder_alloc_init(&proc->alloc);
 
@@ -5405,6 +5406,7 @@ static int binder_node_release(struct binder_node *node, int refs)
 static void binder_deferred_release(struct binder_proc *proc)
 {
        struct binder_context *context = proc->context;
+       struct binder_device *device;
        struct rb_node *n;
        int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
 
@@ -5421,6 +5423,12 @@ static void binder_deferred_release(struct binder_proc *proc)
                context->binder_context_mgr_node = NULL;
        }
        mutex_unlock(&context->context_mgr_node_lock);
+       device = container_of(proc->context, struct binder_device, context);
+       if (refcount_dec_and_test(&device->ref)) {
+               kfree(context->name);
+               kfree(device);
+       }
+       proc->context = NULL;
        binder_inner_proc_lock(proc);
        /*
         * Make sure proc stays alive after we
@@ -6077,6 +6085,7 @@ static int __init init_binder_device(const char *name)
        binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
        binder_device->miscdev.name = name;
 
+       refcount_set(&binder_device->ref, 1);
        binder_device->context.binder_context_mgr_uid = INVALID_UID;
        binder_device->context.name = name;
        mutex_init(&binder_device->context.context_mgr_node_lock);
index ae99109..283d3cb 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
@@ -33,6 +34,7 @@ struct binder_device {
        struct miscdevice miscdev;
        struct binder_context context;
        struct inode *binderfs_inode;
+       refcount_t ref;
 };
 
 /**
index e2580e5..110e41f 100644 (file)
@@ -154,6 +154,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
        if (!name)
                goto err;
 
+       refcount_set(&device->ref, 1);
        device->binderfs_inode = inode;
        device->context.binder_context_mgr_uid = INVALID_UID;
        device->context.name = name;
@@ -257,8 +258,10 @@ static void binderfs_evict_inode(struct inode *inode)
        ida_free(&binderfs_minors, device->miscdev.minor);
        mutex_unlock(&binderfs_minors_mutex);
 
-       kfree(device->context.name);
-       kfree(device);
+       if (refcount_dec_and_test(&device->ref)) {
+               kfree(device->context.name);
+               kfree(device);
+       }
 }
 
 /**
index 8db8c0f..7af74fb 100644 (file)
@@ -91,7 +91,7 @@
 #ifdef GENERAL_DEBUG
 #define PRINTK(args...) printk(args)
 #else
-#define PRINTK(args...)
+#define PRINTK(args...) do {} while (0)
 #endif /* GENERAL_DEBUG */
 
 #ifdef EXTRA_DEBUG
index b8313a0..48efa7a 100644 (file)
@@ -111,7 +111,7 @@ config CFAG12864B
          If unsure, say N.
 
 config CFAG12864B_RATE
-       int "Refresh rate (hertz)"
+       int "Refresh rate (hertz)"
        depends on CFAG12864B
        default "20"
        ---help---
@@ -329,7 +329,7 @@ config PANEL_LCD_PROTO
 
 config PANEL_LCD_PIN_E
        depends on PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
-        int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) "
        range -17 17
        default 14
        ---help---
@@ -344,7 +344,7 @@ config PANEL_LCD_PIN_E
 
 config PANEL_LCD_PIN_RS
        depends on PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
-        int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) "
        range -17 17
        default 17
        ---help---
@@ -359,7 +359,7 @@ config PANEL_LCD_PIN_RS
 
 config PANEL_LCD_PIN_RW
        depends on PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
-        int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) "
        range -17 17
        default 16
        ---help---
@@ -374,7 +374,7 @@ config PANEL_LCD_PIN_RW
 
 config PANEL_LCD_PIN_SCL
        depends on PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
-        int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) "
        range -17 17
        default 1
        ---help---
@@ -389,7 +389,7 @@ config PANEL_LCD_PIN_SCL
 
 config PANEL_LCD_PIN_SDA
        depends on PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
-        int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) "
        range -17 17
        default 2
        ---help---
@@ -404,12 +404,12 @@ config PANEL_LCD_PIN_SDA
 
 config PANEL_LCD_PIN_BL
        depends on PANEL_PROFILE="0" && PANEL_LCD="1"
-        int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) "
+       int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) "
        range -17 17
        default 0
        ---help---
          This describes the number of the parallel port pin to which the LCD 'BL' signal
-          has been connected. It can be :
+         has been connected. It can be :
 
                  0 : no connection (eg: connected to ground)
              1..17 : directly connected to any of these pins on the DB25 plug
index 874c259..c0da382 100644 (file)
@@ -88,7 +88,7 @@ struct charlcd_priv {
                int len;
        } esc_seq;
 
-       unsigned long long drvdata[0];
+       unsigned long long drvdata[];
 };
 
 #define charlcd_to_priv(p)     container_of(p, struct charlcd_priv, lcd)
index efb928e..1cce409 100644 (file)
@@ -356,7 +356,6 @@ static int img_ascii_lcd_probe(struct platform_device *pdev)
        const struct of_device_id *match;
        const struct img_ascii_lcd_config *cfg;
        struct img_ascii_lcd_ctx *ctx;
-       struct resource *res;
        int err;
 
        match = of_match_device(img_ascii_lcd_matches, &pdev->dev);
@@ -378,8 +377,7 @@ static int img_ascii_lcd_probe(struct platform_device *pdev)
                                         &ctx->offset))
                        return -EINVAL;
        } else {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               ctx->base = devm_ioremap_resource(&pdev->dev, res);
+               ctx->base = devm_platform_ioremap_resource(pdev, 0);
                if (IS_ERR(ctx->base))
                        return PTR_ERR(ctx->base);
        }
index 42a6724..dbb0f91 100644 (file)
@@ -718,6 +718,8 @@ static void __device_links_queue_sync_state(struct device *dev,
 {
        struct device_link *link;
 
+       if (!dev_has_sync_state(dev))
+               return;
        if (dev->state_synced)
                return;
 
@@ -745,25 +747,31 @@ static void __device_links_queue_sync_state(struct device *dev,
 /**
  * device_links_flush_sync_list - Call sync_state() on a list of devices
  * @list: List of devices to call sync_state() on
+ * @dont_lock_dev: Device for which lock is already held by the caller
  *
  * Calls sync_state() on all the devices that have been queued for it. This
- * function is used in conjunction with __device_links_queue_sync_state().
+ * function is used in conjunction with __device_links_queue_sync_state(). The
+ * @dont_lock_dev parameter is useful when this function is called from a
+ * context where a device lock is already held.
  */
-static void device_links_flush_sync_list(struct list_head *list)
+static void device_links_flush_sync_list(struct list_head *list,
+                                        struct device *dont_lock_dev)
 {
        struct device *dev, *tmp;
 
        list_for_each_entry_safe(dev, tmp, list, links.defer_sync) {
                list_del_init(&dev->links.defer_sync);
 
-               device_lock(dev);
+               if (dev != dont_lock_dev)
+                       device_lock(dev);
 
                if (dev->bus->sync_state)
                        dev->bus->sync_state(dev);
                else if (dev->driver && dev->driver->sync_state)
                        dev->driver->sync_state(dev);
 
-               device_unlock(dev);
+               if (dev != dont_lock_dev)
+                       device_unlock(dev);
 
                put_device(dev);
        }
@@ -801,7 +809,7 @@ void device_links_supplier_sync_state_resume(void)
 out:
        device_links_write_unlock();
 
-       device_links_flush_sync_list(&sync_list);
+       device_links_flush_sync_list(&sync_list, NULL);
 }
 
 static int sync_state_resume_initcall(void)
@@ -813,7 +821,7 @@ late_initcall(sync_state_resume_initcall);
 
 static void __device_links_supplier_defer_sync(struct device *sup)
 {
-       if (list_empty(&sup->links.defer_sync))
+       if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup))
                list_add_tail(&sup->links.defer_sync, &deferred_sync);
 }
 
@@ -865,6 +873,11 @@ void device_links_driver_bound(struct device *dev)
                        driver_deferred_probe_add(link->consumer);
        }
 
+       if (defer_sync_state_count)
+               __device_links_supplier_defer_sync(dev);
+       else
+               __device_links_queue_sync_state(dev, &sync_list);
+
        list_for_each_entry(link, &dev->links.suppliers, c_node) {
                if (!(link->flags & DL_FLAG_MANAGED))
                        continue;
@@ -883,7 +896,7 @@ void device_links_driver_bound(struct device *dev)
 
        device_links_write_unlock();
 
-       device_links_flush_sync_list(&sync_list);
+       device_links_flush_sync_list(&sync_list, dev);
 }
 
 static void device_link_drop_managed(struct device_link *link)
index 7fa654f..b5ce7b0 100644 (file)
@@ -363,10 +363,10 @@ static void setup_pdev_dma_masks(struct platform_device *pdev)
 {
        if (!pdev->dev.coherent_dma_mask)
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       if (!pdev->dma_mask)
-               pdev->dma_mask = DMA_BIT_MASK(32);
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dma_mask;
+       if (!pdev->dev.dma_mask) {
+               pdev->platform_dma_mask = DMA_BIT_MASK(32);
+               pdev->dev.dma_mask = &pdev->platform_dma_mask;
+       }
 };
 
 /**
@@ -662,20 +662,8 @@ struct platform_device *platform_device_register_full(
        pdev->dev.of_node_reused = pdevinfo->of_node_reused;
 
        if (pdevinfo->dma_mask) {
-               /*
-                * This memory isn't freed when the device is put,
-                * I don't have a nice idea for that though.  Conceptually
-                * dma_mask in struct device should not be a pointer.
-                * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
-                */
-               pdev->dev.dma_mask =
-                       kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-               if (!pdev->dev.dma_mask)
-                       goto err;
-
-               kmemleak_ignore(pdev->dev.dma_mask);
-
-               *pdev->dev.dma_mask = pdevinfo->dma_mask;
+               pdev->platform_dma_mask = pdevinfo->dma_mask;
+               pdev->dev.dma_mask = &pdev->platform_dma_mask;
                pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
        }
 
@@ -700,7 +688,6 @@ struct platform_device *platform_device_register_full(
        if (ret) {
 err:
                ACPI_COMPANION_SET(&pdev->dev, NULL);
-               kfree(pdev->dev.dma_mask);
                platform_device_put(pdev);
                return ERR_PTR(ret);
        }
index 0b081de..de8d354 100644 (file)
@@ -608,6 +608,13 @@ static void software_node_release(struct kobject *kobj)
 {
        struct swnode *swnode = kobj_to_swnode(kobj);
 
+       if (swnode->parent) {
+               ida_simple_remove(&swnode->parent->child_ids, swnode->id);
+               list_del(&swnode->entry);
+       } else {
+               ida_simple_remove(&swnode_root_ids, swnode->id);
+       }
+
        if (swnode->allocated) {
                property_entries_free(swnode->node->properties);
                kfree(swnode->node);
@@ -773,13 +780,6 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
        if (!swnode)
                return;
 
-       if (swnode->parent) {
-               ida_simple_remove(&swnode->parent->child_ids, swnode->id);
-               list_del(&swnode->entry);
-       } else {
-               ida_simple_remove(&swnode_root_ids, swnode->id);
-       }
-
        kobject_put(&swnode->kobj);
 }
 EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
index cd3612e..8ef65c0 100644 (file)
@@ -853,14 +853,17 @@ static void reset_fdc_info(int mode)
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+       unsigned int new_fdc = fdc;
+
        if (drive >= 0 && drive < N_DRIVE) {
-               fdc = FDC(drive);
+               new_fdc = FDC(drive);
                current_drive = drive;
        }
-       if (fdc != 1 && fdc != 0) {
+       if (new_fdc >= N_FDC) {
                pr_info("bad fdc value\n");
                return;
        }
+       fdc = new_fdc;
        set_dor(fdc, ~0, 8);
 #if N_FDC > 1
        set_dor(1 - fdc, ~8, 0);
index 117cfc8..cda5cf9 100644 (file)
@@ -276,7 +276,7 @@ static const struct block_device_operations pcd_bdops = {
        .release        = pcd_block_release,
        .ioctl          = pcd_block_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl          = blkdev_compat_ptr_ioctl,
+       .compat_ioctl   = blkdev_compat_ptr_ioctl,
 #endif
        .check_events   = pcd_block_check_events,
 };
index 5415876..0736248 100644 (file)
@@ -245,13 +245,20 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
        err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
        if (err) {
                virtqueue_kick(vblk->vqs[qid].vq);
-               blk_mq_stop_hw_queue(hctx);
+               /* Don't stop the queue if -ENOMEM: we may have failed to
+                * bounce the buffer due to global resource outage.
+                */
+               if (err == -ENOSPC)
+                       blk_mq_stop_hw_queue(hctx);
                spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
-               /* Out of mem doesn't actually happen, since we fall back
-                * to direct descriptors */
-               if (err == -ENOMEM || err == -ENOSPC)
+               switch (err) {
+               case -ENOSPC:
                        return BLK_STS_DEV_RESOURCE;
-               return BLK_STS_IOERR;
+               case -ENOMEM:
+                       return BLK_STS_RESOURCE;
+               default:
+                       return BLK_STS_IOERR;
+               }
        }
 
        if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
index e2ad6bb..9df516a 100644 (file)
@@ -213,6 +213,7 @@ struct blkfront_info
        struct blk_mq_tag_set tag_set;
        struct blkfront_ring_info *rinfo;
        unsigned int nr_rings;
+       unsigned int rinfo_size;
        /* Save uncomplete reqs and bios for migration. */
        struct list_head requests;
        struct bio_list bio_list;
@@ -259,6 +260,18 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo);
 static void blkfront_gather_backend_features(struct blkfront_info *info);
 static int negotiate_mq(struct blkfront_info *info);
 
+#define for_each_rinfo(info, ptr, idx)                         \
+       for ((ptr) = (info)->rinfo, (idx) = 0;                  \
+            (idx) < (info)->nr_rings;                          \
+            (idx)++, (ptr) = (void *)(ptr) + (info)->rinfo_size)
+
+static inline struct blkfront_ring_info *
+get_rinfo(const struct blkfront_info *info, unsigned int i)
+{
+       BUG_ON(i >= info->nr_rings);
+       return (void *)info->rinfo + i * info->rinfo_size;
+}
+
 static int get_id_from_freelist(struct blkfront_ring_info *rinfo)
 {
        unsigned long free = rinfo->shadow_free;
@@ -883,8 +896,7 @@ static blk_status_t blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
        struct blkfront_info *info = hctx->queue->queuedata;
        struct blkfront_ring_info *rinfo = NULL;
 
-       BUG_ON(info->nr_rings <= qid);
-       rinfo = &info->rinfo[qid];
+       rinfo = get_rinfo(info, qid);
        blk_mq_start_request(qd->rq);
        spin_lock_irqsave(&rinfo->ring_lock, flags);
        if (RING_FULL(&rinfo->ring))
@@ -1181,6 +1193,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 static void xlvbd_release_gendisk(struct blkfront_info *info)
 {
        unsigned int minor, nr_minors, i;
+       struct blkfront_ring_info *rinfo;
 
        if (info->rq == NULL)
                return;
@@ -1188,9 +1201,7 @@ static void xlvbd_release_gendisk(struct blkfront_info *info)
        /* No more blkif_request(). */
        blk_mq_stop_hw_queues(info->rq);
 
-       for (i = 0; i < info->nr_rings; i++) {
-               struct blkfront_ring_info *rinfo = &info->rinfo[i];
-
+       for_each_rinfo(info, rinfo, i) {
                /* No more gnttab callback work. */
                gnttab_cancel_free_callback(&rinfo->callback);
 
@@ -1339,6 +1350,7 @@ free_shadow:
 static void blkif_free(struct blkfront_info *info, int suspend)
 {
        unsigned int i;
+       struct blkfront_ring_info *rinfo;
 
        /* Prevent new requests being issued until we fix things up. */
        info->connected = suspend ?
@@ -1347,8 +1359,8 @@ static void blkif_free(struct blkfront_info *info, int suspend)
        if (info->rq)
                blk_mq_stop_hw_queues(info->rq);
 
-       for (i = 0; i < info->nr_rings; i++)
-               blkif_free_ring(&info->rinfo[i]);
+       for_each_rinfo(info, rinfo, i)
+               blkif_free_ring(rinfo);
 
        kvfree(info->rinfo);
        info->rinfo = NULL;
@@ -1775,6 +1787,7 @@ static int talk_to_blkback(struct xenbus_device *dev,
        int err;
        unsigned int i, max_page_order;
        unsigned int ring_page_order;
+       struct blkfront_ring_info *rinfo;
 
        if (!info)
                return -ENODEV;
@@ -1788,9 +1801,7 @@ static int talk_to_blkback(struct xenbus_device *dev,
        if (err)
                goto destroy_blkring;
 
-       for (i = 0; i < info->nr_rings; i++) {
-               struct blkfront_ring_info *rinfo = &info->rinfo[i];
-
+       for_each_rinfo(info, rinfo, i) {
                /* Create shared ring, alloc event channel. */
                err = setup_blkring(dev, rinfo);
                if (err)
@@ -1815,7 +1826,7 @@ again:
 
        /* We already got the number of queues/rings in _probe */
        if (info->nr_rings == 1) {
-               err = write_per_ring_nodes(xbt, &info->rinfo[0], dev->nodename);
+               err = write_per_ring_nodes(xbt, info->rinfo, dev->nodename);
                if (err)
                        goto destroy_blkring;
        } else {
@@ -1837,10 +1848,10 @@ again:
                        goto abort_transaction;
                }
 
-               for (i = 0; i < info->nr_rings; i++) {
+               for_each_rinfo(info, rinfo, i) {
                        memset(path, 0, pathsize);
                        snprintf(path, pathsize, "%s/queue-%u", dev->nodename, i);
-                       err = write_per_ring_nodes(xbt, &info->rinfo[i], path);
+                       err = write_per_ring_nodes(xbt, rinfo, path);
                        if (err) {
                                kfree(path);
                                goto destroy_blkring;
@@ -1868,9 +1879,8 @@ again:
                goto destroy_blkring;
        }
 
-       for (i = 0; i < info->nr_rings; i++) {
+       for_each_rinfo(info, rinfo, i) {
                unsigned int j;
-               struct blkfront_ring_info *rinfo = &info->rinfo[i];
 
                for (j = 0; j < BLK_RING_SIZE(info); j++)
                        rinfo->shadow[j].req.u.rw.id = j + 1;
@@ -1900,6 +1910,7 @@ static int negotiate_mq(struct blkfront_info *info)
 {
        unsigned int backend_max_queues;
        unsigned int i;
+       struct blkfront_ring_info *rinfo;
 
        BUG_ON(info->nr_rings);
 
@@ -1911,20 +1922,16 @@ static int negotiate_mq(struct blkfront_info *info)
        if (!info->nr_rings)
                info->nr_rings = 1;
 
-       info->rinfo = kvcalloc(info->nr_rings,
-                              struct_size(info->rinfo, shadow,
-                                          BLK_RING_SIZE(info)),
-                              GFP_KERNEL);
+       info->rinfo_size = struct_size(info->rinfo, shadow,
+                                      BLK_RING_SIZE(info));
+       info->rinfo = kvcalloc(info->nr_rings, info->rinfo_size, GFP_KERNEL);
        if (!info->rinfo) {
                xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure");
                info->nr_rings = 0;
                return -ENOMEM;
        }
 
-       for (i = 0; i < info->nr_rings; i++) {
-               struct blkfront_ring_info *rinfo;
-
-               rinfo = &info->rinfo[i];
+       for_each_rinfo(info, rinfo, i) {
                INIT_LIST_HEAD(&rinfo->indirect_pages);
                INIT_LIST_HEAD(&rinfo->grants);
                rinfo->dev_info = info;
@@ -2017,6 +2024,7 @@ static int blkif_recover(struct blkfront_info *info)
        int rc;
        struct bio *bio;
        unsigned int segs;
+       struct blkfront_ring_info *rinfo;
 
        blkfront_gather_backend_features(info);
        /* Reset limits changed by blk_mq_update_nr_hw_queues(). */
@@ -2024,9 +2032,7 @@ static int blkif_recover(struct blkfront_info *info)
        segs = info->max_indirect_segments ? : BLKIF_MAX_SEGMENTS_PER_REQUEST;
        blk_queue_max_segments(info->rq, segs / GRANTS_PER_PSEG);
 
-       for (r_index = 0; r_index < info->nr_rings; r_index++) {
-               struct blkfront_ring_info *rinfo = &info->rinfo[r_index];
-
+       for_each_rinfo(info, rinfo, r_index) {
                rc = blkfront_setup_indirect(rinfo);
                if (rc)
                        return rc;
@@ -2036,10 +2042,7 @@ static int blkif_recover(struct blkfront_info *info)
        /* Now safe for us to use the shared ring */
        info->connected = BLKIF_STATE_CONNECTED;
 
-       for (r_index = 0; r_index < info->nr_rings; r_index++) {
-               struct blkfront_ring_info *rinfo;
-
-               rinfo = &info->rinfo[r_index];
+       for_each_rinfo(info, rinfo, r_index) {
                /* Kick any other new requests queued since we resumed */
                kick_pending_request_queues(rinfo);
        }
@@ -2072,13 +2075,13 @@ static int blkfront_resume(struct xenbus_device *dev)
        struct blkfront_info *info = dev_get_drvdata(&dev->dev);
        int err = 0;
        unsigned int i, j;
+       struct blkfront_ring_info *rinfo;
 
        dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename);
 
        bio_list_init(&info->bio_list);
        INIT_LIST_HEAD(&info->requests);
-       for (i = 0; i < info->nr_rings; i++) {
-               struct blkfront_ring_info *rinfo = &info->rinfo[i];
+       for_each_rinfo(info, rinfo, i) {
                struct bio_list merge_bio;
                struct blk_shadow *shadow = rinfo->shadow;
 
@@ -2337,6 +2340,7 @@ static void blkfront_connect(struct blkfront_info *info)
        unsigned int binfo;
        char *envp[] = { "RESIZE=1", NULL };
        int err, i;
+       struct blkfront_ring_info *rinfo;
 
        switch (info->connected) {
        case BLKIF_STATE_CONNECTED:
@@ -2394,8 +2398,8 @@ static void blkfront_connect(struct blkfront_info *info)
                                                    "physical-sector-size",
                                                    sector_size);
        blkfront_gather_backend_features(info);
-       for (i = 0; i < info->nr_rings; i++) {
-               err = blkfront_setup_indirect(&info->rinfo[i]);
+       for_each_rinfo(info, rinfo, i) {
+               err = blkfront_setup_indirect(rinfo);
                if (err) {
                        xenbus_dev_fatal(info->xbdev, err, "setup_indirect at %s",
                                         info->xbdev->otherend);
@@ -2416,8 +2420,8 @@ static void blkfront_connect(struct blkfront_info *info)
 
        /* Kick pending requests. */
        info->connected = BLKIF_STATE_CONNECTED;
-       for (i = 0; i < info->nr_rings; i++)
-               kick_pending_request_queues(&info->rinfo[i]);
+       for_each_rinfo(info, rinfo, i)
+               kick_pending_request_queues(rinfo);
 
        device_add_disk(&info->xbdev->dev, info->gd, NULL);
 
@@ -2652,9 +2656,9 @@ static void purge_persistent_grants(struct blkfront_info *info)
 {
        unsigned int i;
        unsigned long flags;
+       struct blkfront_ring_info *rinfo;
 
-       for (i = 0; i < info->nr_rings; i++) {
-               struct blkfront_ring_info *rinfo = &info->rinfo[i];
+       for_each_rinfo(info, rinfo, i) {
                struct grant *gnt_list_entry, *tmp;
 
                spin_lock_irqsave(&rinfo->ring_lock, flags);
index f702c85..6113fc0 100644 (file)
@@ -1400,7 +1400,7 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
 }
 
 /* 1-wire needs module's internal clocks enabled for reset */
-static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata)
+static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata)
 {
        int offset = 0x0c;      /* HDQ_CTRL_STATUS */
        u16 val;
@@ -1488,7 +1488,7 @@ static void sysc_init_module_quirks(struct sysc *ddata)
                return;
 
        if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) {
-               ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w;
+               ddata->clk_disable_quirk = sysc_pre_reset_quirk_hdq1w;
 
                return;
        }
index 886b263..c51292c 100644 (file)
@@ -519,7 +519,7 @@ static const struct block_device_operations gdrom_bdops = {
        .check_events           = gdrom_bdops_check_events,
        .ioctl                  = gdrom_bdops_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl                  = blkdev_compat_ptr_ioctl,
+       .compat_ioctl           = blkdev_compat_ptr_ioctl,
 #endif
 };
 
index c78127c..638c693 100644 (file)
@@ -194,7 +194,7 @@ static int platform_ipmi_probe(struct platform_device *pdev)
        else
                io.slave_addr = slave_addr;
 
-       io.irq = platform_get_irq(pdev, 0);
+       io.irq = platform_get_irq_optional(pdev, 0);
        if (io.irq > 0)
                io.irq_setup = ipmi_std_irq_setup;
        else
@@ -378,7 +378,7 @@ static int acpi_ipmi_probe(struct platform_device *pdev)
                io.irq = tmp;
                io.irq_setup = acpi_gpe_irq_setup;
        } else {
-               int irq = platform_get_irq(pdev, 0);
+               int irq = platform_get_irq_optional(pdev, 0);
 
                if (irq > 0) {
                        io.irq = irq;
index cbe6c94..808874b 100644 (file)
@@ -1076,9 +1076,17 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
                        pol = policy->last_policy;
                } else if (def_gov) {
                        pol = cpufreq_parse_policy(def_gov->name);
-               } else {
-                       return -ENODATA;
+                       /*
+                        * In case the default governor is neiter "performance"
+                        * nor "powersave", fall back to the initial policy
+                        * value set by the driver.
+                        */
+                       if (pol == CPUFREQ_POLICY_UNKNOWN)
+                               pol = policy->policy;
                }
+               if (pol != CPUFREQ_POLICY_PERFORMANCE &&
+                   pol != CPUFREQ_POLICY_POWERSAVE)
+                       return -ENODATA;
        }
 
        return cpufreq_set_policy(policy, gov, pol);
index cceee8b..7dcf209 100644 (file)
@@ -738,7 +738,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
 {
        struct devfreq *devfreq;
        struct devfreq_governor *governor;
-       static atomic_t devfreq_no = ATOMIC_INIT(-1);
        int err = 0;
 
        if (!dev || !profile || !governor_name) {
@@ -800,8 +799,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
        atomic_set(&devfreq->suspend_count, 0);
 
-       dev_set_name(&devfreq->dev, "devfreq%d",
-                               atomic_inc_return(&devfreq_no));
+       dev_set_name(&devfreq->dev, "%s", dev_name(dev));
        err = device_register(&devfreq->dev);
        if (err) {
                mutex_unlock(&devfreq->lock);
index d409785..c343c7c 100644 (file)
@@ -108,6 +108,7 @@ static int dma_buf_release(struct inode *inode, struct file *file)
                dma_resv_fini(dmabuf->resv);
 
        module_put(dmabuf->owner);
+       kfree(dmabuf->name);
        kfree(dmabuf);
        return 0;
 }
index e51d836..1092d4c 100644 (file)
@@ -1947,8 +1947,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
                return;
        }
 
-       spin_lock(&cohc->lock);
-
        /*
         * When we reach this point, at least one queue item
         * should have been moved over from cohc->queue to
@@ -1969,8 +1967,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc)
        if (coh901318_queue_start(cohc) == NULL)
                cohc->busy = 0;
 
-       spin_unlock(&cohc->lock);
-
        /*
         * This tasklet will remove items from cohc->active
         * and thus terminates them.
index 1d73478..df47be6 100644 (file)
@@ -204,6 +204,7 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
        minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL);
        if (minor < 0) {
                rc = minor;
+               kfree(dev);
                goto ida_err;
        }
 
@@ -212,7 +213,6 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
        rc = device_register(dev);
        if (rc < 0) {
                dev_err(&idxd->pdev->dev, "device register failed\n");
-               put_device(dev);
                goto dev_reg_err;
        }
        idxd_cdev->minor = minor;
@@ -221,8 +221,8 @@ static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
 
  dev_reg_err:
        ida_simple_remove(&cdev_ctx->minor_ida, MINOR(dev->devt));
+       put_device(dev);
  ida_err:
-       kfree(dev);
        idxd_cdev->dev = NULL;
        return rc;
 }
index 6d907fe..6ca6e52 100644 (file)
@@ -124,6 +124,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_device_config(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_warn(dev, "Device config failed: %d\n", rc);
                        return rc;
                }
@@ -132,6 +133,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_device_enable(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_warn(dev, "Device enable failed: %d\n", rc);
                        return rc;
                }
@@ -142,6 +144,7 @@ static int idxd_config_bus_probe(struct device *dev)
                rc = idxd_register_dma_device(idxd);
                if (rc < 0) {
                        spin_unlock_irqrestore(&idxd->dev_lock, flags);
+                       module_put(THIS_MODULE);
                        dev_dbg(dev, "Failed to register dmaengine device\n");
                        return rc;
                }
@@ -516,7 +519,7 @@ static ssize_t group_tokens_reserved_store(struct device *dev,
        if (val > idxd->max_tokens)
                return -EINVAL;
 
-       if (val > idxd->nr_tokens)
+       if (val > idxd->nr_tokens + group->tokens_reserved)
                return -EINVAL;
 
        group->tokens_reserved = val;
@@ -901,6 +904,20 @@ static ssize_t wq_size_show(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%u\n", wq->size);
 }
 
+static int total_claimed_wq_size(struct idxd_device *idxd)
+{
+       int i;
+       int wq_size = 0;
+
+       for (i = 0; i < idxd->max_wqs; i++) {
+               struct idxd_wq *wq = &idxd->wqs[i];
+
+               wq_size += wq->size;
+       }
+
+       return wq_size;
+}
+
 static ssize_t wq_size_store(struct device *dev,
                             struct device_attribute *attr, const char *buf,
                             size_t count)
@@ -920,7 +937,7 @@ static ssize_t wq_size_store(struct device *dev,
        if (wq->state != IDXD_WQ_DISABLED)
                return -EPERM;
 
-       if (size > idxd->max_wq_size)
+       if (size + total_claimed_wq_size(idxd) - wq->size > idxd->max_wq_size)
                return -EINVAL;
 
        wq->size = size;
@@ -999,12 +1016,14 @@ static ssize_t wq_type_store(struct device *dev,
                return -EPERM;
 
        old_type = wq->type;
-       if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_KERNEL]))
+       if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_NONE]))
+               wq->type = IDXD_WQT_NONE;
+       else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_KERNEL]))
                wq->type = IDXD_WQT_KERNEL;
        else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_USER]))
                wq->type = IDXD_WQT_USER;
        else
-               wq->type = IDXD_WQT_NONE;
+               return -EINVAL;
 
        /* If we are changing queue type, clear the name */
        if (wq->type != old_type)
index 066b21a..4d4477d 100644 (file)
@@ -1331,13 +1331,14 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
        sdma_channel_synchronize(chan);
 
-       if (sdmac->event_id0)
+       if (sdmac->event_id0 >= 0)
                sdma_event_disable(sdmac, sdmac->event_id0);
        if (sdmac->event_id1)
                sdma_event_disable(sdmac, sdmac->event_id1);
 
        sdmac->event_id0 = 0;
        sdmac->event_id1 = 0;
+       sdmac->context_loaded = false;
 
        sdma_set_channel_priority(sdmac, 0);
 
@@ -1631,7 +1632,7 @@ static int sdma_config(struct dma_chan *chan,
        memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
 
        /* Set ENBLn earlier to make sure dma request triggered after that */
-       if (sdmac->event_id0) {
+       if (sdmac->event_id0 >= 0) {
                if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
                        return -EINVAL;
                sdma_event_enable(sdmac, sdmac->event_id0);
index 3a45079..4a750e2 100644 (file)
@@ -281,7 +281,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get(
 
        /* Do not allocate if desc are waiting for ack */
        list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
-               if (async_tx_test_ack(&dma_desc->txd)) {
+               if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) {
                        list_del(&dma_desc->node);
                        spin_unlock_irqrestore(&tdc->lock, flags);
                        dma_desc->txd.flags = 0;
@@ -756,10 +756,6 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
        bool was_busy;
 
        spin_lock_irqsave(&tdc->lock, flags);
-       if (list_empty(&tdc->pending_sg_req)) {
-               spin_unlock_irqrestore(&tdc->lock, flags);
-               return 0;
-       }
 
        if (!tdc->busy)
                goto skip_dma_stop;
index ea79c2d..0536866 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
@@ -96,6 +97,24 @@ struct udma_match_data {
        u32 level_start_idx[];
 };
 
+struct udma_hwdesc {
+       size_t cppi5_desc_size;
+       void *cppi5_desc_vaddr;
+       dma_addr_t cppi5_desc_paddr;
+
+       /* TR descriptor internal pointers */
+       void *tr_req_base;
+       struct cppi5_tr_resp_t *tr_resp_base;
+};
+
+struct udma_rx_flush {
+       struct udma_hwdesc hwdescs[2];
+
+       size_t buffer_size;
+       void *buffer_vaddr;
+       dma_addr_t buffer_paddr;
+};
+
 struct udma_dev {
        struct dma_device ddev;
        struct device *dev;
@@ -112,6 +131,8 @@ struct udma_dev {
        struct list_head desc_to_purge;
        spinlock_t lock;
 
+       struct udma_rx_flush rx_flush;
+
        int tchan_cnt;
        int echan_cnt;
        int rchan_cnt;
@@ -130,16 +151,6 @@ struct udma_dev {
        u32 psil_base;
 };
 
-struct udma_hwdesc {
-       size_t cppi5_desc_size;
-       void *cppi5_desc_vaddr;
-       dma_addr_t cppi5_desc_paddr;
-
-       /* TR descriptor internal pointers */
-       void *tr_req_base;
-       struct cppi5_tr_resp_t *tr_resp_base;
-};
-
 struct udma_desc {
        struct virt_dma_desc vd;
 
@@ -169,7 +180,7 @@ enum udma_chan_state {
 
 struct udma_tx_drain {
        struct delayed_work work;
-       unsigned long jiffie;
+       ktime_t tstamp;
        u32 residue;
 };
 
@@ -502,7 +513,7 @@ static bool udma_is_chan_paused(struct udma_chan *uc)
 {
        u32 val, pause_mask;
 
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                val = udma_rchanrt_read(uc->rchan,
                                        UDMA_RCHAN_RT_PEER_RT_EN_REG);
@@ -551,12 +562,17 @@ static void udma_sync_for_device(struct udma_chan *uc, int idx)
        }
 }
 
+static inline dma_addr_t udma_get_rx_flush_hwdesc_paddr(struct udma_chan *uc)
+{
+       return uc->ud->rx_flush.hwdescs[uc->config.pkt_mode].cppi5_desc_paddr;
+}
+
 static int udma_push_to_ring(struct udma_chan *uc, int idx)
 {
        struct udma_desc *d = uc->desc;
-
        struct k3_ring *ring = NULL;
-       int ret = -EINVAL;
+       dma_addr_t paddr;
+       int ret;
 
        switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
@@ -567,21 +583,37 @@ static int udma_push_to_ring(struct udma_chan *uc, int idx)
                ring = uc->tchan->t_ring;
                break;
        default:
-               break;
+               return -EINVAL;
        }
 
-       if (ring) {
-               dma_addr_t desc_addr = udma_curr_cppi5_desc_paddr(d, idx);
+       /* RX flush packet: idx == -1 is only passed in case of DEV_TO_MEM */
+       if (idx == -1) {
+               paddr = udma_get_rx_flush_hwdesc_paddr(uc);
+       } else {
+               paddr = udma_curr_cppi5_desc_paddr(d, idx);
 
                wmb(); /* Ensure that writes are not moved over this point */
                udma_sync_for_device(uc, idx);
-               ret = k3_ringacc_ring_push(ring, &desc_addr);
-               uc->in_ring_cnt++;
        }
 
+       ret = k3_ringacc_ring_push(ring, &paddr);
+       if (!ret)
+               uc->in_ring_cnt++;
+
        return ret;
 }
 
+static bool udma_desc_is_rx_flush(struct udma_chan *uc, dma_addr_t addr)
+{
+       if (uc->config.dir != DMA_DEV_TO_MEM)
+               return false;
+
+       if (addr == udma_get_rx_flush_hwdesc_paddr(uc))
+               return true;
+
+       return false;
+}
+
 static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
 {
        struct k3_ring *ring = NULL;
@@ -610,6 +642,10 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr)
                if (cppi5_desc_is_tdcm(*addr))
                        return ret;
 
+               /* Check for flush descriptor */
+               if (udma_desc_is_rx_flush(uc, *addr))
+                       return -ENOENT;
+
                d = udma_udma_desc_from_paddr(uc, *addr);
 
                if (d)
@@ -890,6 +926,9 @@ static int udma_stop(struct udma_chan *uc)
 
        switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
+               if (!uc->cyclic && !uc->desc)
+                       udma_push_to_ring(uc, -1);
+
                udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG,
                                   UDMA_PEER_RT_EN_ENABLE |
                                   UDMA_PEER_RT_EN_TEARDOWN);
@@ -946,9 +985,10 @@ static bool udma_is_desc_really_done(struct udma_chan *uc, struct udma_desc *d)
        peer_bcnt = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG);
        bcnt = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_BCNT_REG);
 
+       /* Transfer is incomplete, store current residue and time stamp */
        if (peer_bcnt < bcnt) {
                uc->tx_drain.residue = bcnt - peer_bcnt;
-               uc->tx_drain.jiffie = jiffies;
+               uc->tx_drain.tstamp = ktime_get();
                return false;
        }
 
@@ -961,35 +1001,59 @@ static void udma_check_tx_completion(struct work_struct *work)
                                            tx_drain.work.work);
        bool desc_done = true;
        u32 residue_diff;
-       unsigned long jiffie_diff, delay;
+       ktime_t time_diff;
+       unsigned long delay;
+
+       while (1) {
+               if (uc->desc) {
+                       /* Get previous residue and time stamp */
+                       residue_diff = uc->tx_drain.residue;
+                       time_diff = uc->tx_drain.tstamp;
+                       /*
+                        * Get current residue and time stamp or see if
+                        * transfer is complete
+                        */
+                       desc_done = udma_is_desc_really_done(uc, uc->desc);
+               }
 
-       if (uc->desc) {
-               residue_diff = uc->tx_drain.residue;
-               jiffie_diff = uc->tx_drain.jiffie;
-               desc_done = udma_is_desc_really_done(uc, uc->desc);
-       }
-
-       if (!desc_done) {
-               jiffie_diff = uc->tx_drain.jiffie - jiffie_diff;
-               residue_diff -= uc->tx_drain.residue;
-               if (residue_diff) {
-                       /* Try to guess when we should check next time */
-                       residue_diff /= jiffie_diff;
-                       delay = uc->tx_drain.residue / residue_diff / 3;
-                       if (jiffies_to_msecs(delay) < 5)
-                               delay = 0;
-               } else {
-                       /* No progress, check again in 1 second  */
-                       delay = HZ;
+               if (!desc_done) {
+                       /*
+                        * Find the time delta and residue delta w.r.t
+                        * previous poll
+                        */
+                       time_diff = ktime_sub(uc->tx_drain.tstamp,
+                                             time_diff) + 1;
+                       residue_diff -= uc->tx_drain.residue;
+                       if (residue_diff) {
+                               /*
+                                * Try to guess when we should check
+                                * next time by calculating rate at
+                                * which data is being drained at the
+                                * peer device
+                                */
+                               delay = (time_diff / residue_diff) *
+                                       uc->tx_drain.residue;
+                       } else {
+                               /* No progress, check again in 1 second  */
+                               schedule_delayed_work(&uc->tx_drain.work, HZ);
+                               break;
+                       }
+
+                       usleep_range(ktime_to_us(delay),
+                                    ktime_to_us(delay) + 10);
+                       continue;
                }
 
-               schedule_delayed_work(&uc->tx_drain.work, delay);
-       } else if (uc->desc) {
-               struct udma_desc *d = uc->desc;
+               if (uc->desc) {
+                       struct udma_desc *d = uc->desc;
 
-               uc->bcnt += d->residue;
-               udma_start(uc);
-               vchan_cookie_complete(&d->vd);
+                       uc->bcnt += d->residue;
+                       udma_start(uc);
+                       vchan_cookie_complete(&d->vd);
+                       break;
+               }
+
+               break;
        }
 }
 
@@ -1033,29 +1097,27 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data)
                        goto out;
                }
 
-               if (uc->cyclic) {
-                       /* push the descriptor back to the ring */
-                       if (d == uc->desc) {
+               if (d == uc->desc) {
+                       /* active descriptor */
+                       if (uc->cyclic) {
                                udma_cyclic_packet_elapsed(uc);
                                vchan_cyclic_callback(&d->vd);
-                       }
-               } else {
-                       bool desc_done = false;
-
-                       if (d == uc->desc) {
-                               desc_done = udma_is_desc_really_done(uc, d);
-
-                               if (desc_done) {
+                       } else {
+                               if (udma_is_desc_really_done(uc, d)) {
                                        uc->bcnt += d->residue;
                                        udma_start(uc);
+                                       vchan_cookie_complete(&d->vd);
                                } else {
                                        schedule_delayed_work(&uc->tx_drain.work,
                                                              0);
                                }
                        }
-
-                       if (desc_done)
-                               vchan_cookie_complete(&d->vd);
+               } else {
+                       /*
+                        * terminated descriptor, mark the descriptor as
+                        * completed to update the channel's cookie marker
+                        */
+                       dma_cookie_complete(&d->vd.tx);
                }
        }
 out:
@@ -1965,36 +2027,81 @@ static struct udma_desc *udma_alloc_tr_desc(struct udma_chan *uc,
        return d;
 }
 
+/**
+ * udma_get_tr_counters - calculate TR counters for a given length
+ * @len: Length of the trasnfer
+ * @align_to: Preferred alignment
+ * @tr0_cnt0: First TR icnt0
+ * @tr0_cnt1: First TR icnt1
+ * @tr1_cnt0: Second (if used) TR icnt0
+ *
+ * For len < SZ_64K only one TR is enough, tr1_cnt0 is not updated
+ * For len >= SZ_64K two TRs are used in a simple way:
+ * First TR: SZ_64K-alignment blocks (tr0_cnt0, tr0_cnt1)
+ * Second TR: the remaining length (tr1_cnt0)
+ *
+ * Returns the number of TRs the length needs (1 or 2)
+ * -EINVAL if the length can not be supported
+ */
+static int udma_get_tr_counters(size_t len, unsigned long align_to,
+                               u16 *tr0_cnt0, u16 *tr0_cnt1, u16 *tr1_cnt0)
+{
+       if (len < SZ_64K) {
+               *tr0_cnt0 = len;
+               *tr0_cnt1 = 1;
+
+               return 1;
+       }
+
+       if (align_to > 3)
+               align_to = 3;
+
+realign:
+       *tr0_cnt0 = SZ_64K - BIT(align_to);
+       if (len / *tr0_cnt0 >= SZ_64K) {
+               if (align_to) {
+                       align_to--;
+                       goto realign;
+               }
+               return -EINVAL;
+       }
+
+       *tr0_cnt1 = len / *tr0_cnt0;
+       *tr1_cnt0 = len % *tr0_cnt0;
+
+       return 2;
+}
+
 static struct udma_desc *
 udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
                      unsigned int sglen, enum dma_transfer_direction dir,
                      unsigned long tx_flags, void *context)
 {
-       enum dma_slave_buswidth dev_width;
        struct scatterlist *sgent;
        struct udma_desc *d;
-       size_t tr_size;
        struct cppi5_tr_type1_t *tr_req = NULL;
+       u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
        unsigned int i;
-       u32 burst;
+       size_t tr_size;
+       int num_tr = 0;
+       int tr_idx = 0;
 
-       if (dir == DMA_DEV_TO_MEM) {
-               dev_width = uc->cfg.src_addr_width;
-               burst = uc->cfg.src_maxburst;
-       } else if (dir == DMA_MEM_TO_DEV) {
-               dev_width = uc->cfg.dst_addr_width;
-               burst = uc->cfg.dst_maxburst;
-       } else {
-               dev_err(uc->ud->dev, "%s: bad direction?\n", __func__);
+       if (!is_slave_direction(dir)) {
+               dev_err(uc->ud->dev, "Only slave cyclic is supported\n");
                return NULL;
        }
 
-       if (!burst)
-               burst = 1;
+       /* estimate the number of TRs we will need */
+       for_each_sg(sgl, sgent, sglen, i) {
+               if (sg_dma_len(sgent) < SZ_64K)
+                       num_tr++;
+               else
+                       num_tr += 2;
+       }
 
        /* Now allocate and setup the descriptor. */
        tr_size = sizeof(struct cppi5_tr_type1_t);
-       d = udma_alloc_tr_desc(uc, tr_size, sglen, dir);
+       d = udma_alloc_tr_desc(uc, tr_size, num_tr, dir);
        if (!d)
                return NULL;
 
@@ -2002,19 +2109,46 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
        tr_req = d->hwdesc[0].tr_req_base;
        for_each_sg(sgl, sgent, sglen, i) {
-               d->residue += sg_dma_len(sgent);
+               dma_addr_t sg_addr = sg_dma_address(sgent);
+
+               num_tr = udma_get_tr_counters(sg_dma_len(sgent), __ffs(sg_addr),
+                                             &tr0_cnt0, &tr0_cnt1, &tr1_cnt0);
+               if (num_tr < 0) {
+                       dev_err(uc->ud->dev, "size %u is not supported\n",
+                               sg_dma_len(sgent));
+                       udma_free_hwdesc(uc, d);
+                       kfree(d);
+                       return NULL;
+               }
 
                cppi5_tr_init(&tr_req[i].flags, CPPI5_TR_TYPE1, false, false,
                              CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
                cppi5_tr_csf_set(&tr_req[i].flags, CPPI5_TR_CSF_SUPR_EVT);
 
-               tr_req[i].addr = sg_dma_address(sgent);
-               tr_req[i].icnt0 = burst * dev_width;
-               tr_req[i].dim1 = burst * dev_width;
-               tr_req[i].icnt1 = sg_dma_len(sgent) / tr_req[i].icnt0;
+               tr_req[tr_idx].addr = sg_addr;
+               tr_req[tr_idx].icnt0 = tr0_cnt0;
+               tr_req[tr_idx].icnt1 = tr0_cnt1;
+               tr_req[tr_idx].dim1 = tr0_cnt0;
+               tr_idx++;
+
+               if (num_tr == 2) {
+                       cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
+                                     false, false,
+                                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
+                                        CPPI5_TR_CSF_SUPR_EVT);
+
+                       tr_req[tr_idx].addr = sg_addr + tr0_cnt1 * tr0_cnt0;
+                       tr_req[tr_idx].icnt0 = tr1_cnt0;
+                       tr_req[tr_idx].icnt1 = 1;
+                       tr_req[tr_idx].dim1 = tr1_cnt0;
+                       tr_idx++;
+               }
+
+               d->residue += sg_dma_len(sgent);
        }
 
-       cppi5_tr_csf_set(&tr_req[i - 1].flags, CPPI5_TR_CSF_EOP);
+       cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, CPPI5_TR_CSF_EOP);
 
        return d;
 }
@@ -2319,47 +2453,66 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
                        size_t buf_len, size_t period_len,
                        enum dma_transfer_direction dir, unsigned long flags)
 {
-       enum dma_slave_buswidth dev_width;
        struct udma_desc *d;
-       size_t tr_size;
+       size_t tr_size, period_addr;
        struct cppi5_tr_type1_t *tr_req;
-       unsigned int i;
        unsigned int periods = buf_len / period_len;
-       u32 burst;
+       u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+       unsigned int i;
+       int num_tr;
 
-       if (dir == DMA_DEV_TO_MEM) {
-               dev_width = uc->cfg.src_addr_width;
-               burst = uc->cfg.src_maxburst;
-       } else if (dir == DMA_MEM_TO_DEV) {
-               dev_width = uc->cfg.dst_addr_width;
-               burst = uc->cfg.dst_maxburst;
-       } else {
-               dev_err(uc->ud->dev, "%s: bad direction?\n", __func__);
+       if (!is_slave_direction(dir)) {
+               dev_err(uc->ud->dev, "Only slave cyclic is supported\n");
                return NULL;
        }
 
-       if (!burst)
-               burst = 1;
+       num_tr = udma_get_tr_counters(period_len, __ffs(buf_addr), &tr0_cnt0,
+                                     &tr0_cnt1, &tr1_cnt0);
+       if (num_tr < 0) {
+               dev_err(uc->ud->dev, "size %zu is not supported\n",
+                       period_len);
+               return NULL;
+       }
 
        /* Now allocate and setup the descriptor. */
        tr_size = sizeof(struct cppi5_tr_type1_t);
-       d = udma_alloc_tr_desc(uc, tr_size, periods, dir);
+       d = udma_alloc_tr_desc(uc, tr_size, periods * num_tr, dir);
        if (!d)
                return NULL;
 
        tr_req = d->hwdesc[0].tr_req_base;
+       period_addr = buf_addr;
        for (i = 0; i < periods; i++) {
-               cppi5_tr_init(&tr_req[i].flags, CPPI5_TR_TYPE1, false, false,
-                             CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+               int tr_idx = i * num_tr;
 
-               tr_req[i].addr = buf_addr + period_len * i;
-               tr_req[i].icnt0 = dev_width;
-               tr_req[i].icnt1 = period_len / dev_width;
-               tr_req[i].dim1 = dev_width;
+               cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1, false,
+                             false, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+
+               tr_req[tr_idx].addr = period_addr;
+               tr_req[tr_idx].icnt0 = tr0_cnt0;
+               tr_req[tr_idx].icnt1 = tr0_cnt1;
+               tr_req[tr_idx].dim1 = tr0_cnt0;
+
+               if (num_tr == 2) {
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
+                                        CPPI5_TR_CSF_SUPR_EVT);
+                       tr_idx++;
+
+                       cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
+                                     false, false,
+                                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+
+                       tr_req[tr_idx].addr = period_addr + tr0_cnt1 * tr0_cnt0;
+                       tr_req[tr_idx].icnt0 = tr1_cnt0;
+                       tr_req[tr_idx].icnt1 = 1;
+                       tr_req[tr_idx].dim1 = tr1_cnt0;
+               }
 
                if (!(flags & DMA_PREP_INTERRUPT))
-                       cppi5_tr_csf_set(&tr_req[i].flags,
+                       cppi5_tr_csf_set(&tr_req[tr_idx].flags,
                                         CPPI5_TR_CSF_SUPR_EVT);
+
+               period_addr += period_len;
        }
 
        return d;
@@ -2517,29 +2670,12 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                return NULL;
        }
 
-       if (len < SZ_64K) {
-               num_tr = 1;
-               tr0_cnt0 = len;
-               tr0_cnt1 = 1;
-       } else {
-               unsigned long align_to = __ffs(src | dest);
-
-               if (align_to > 3)
-                       align_to = 3;
-               /*
-                * Keep simple: tr0: SZ_64K-alignment blocks,
-                *              tr1: the remaining
-                */
-               num_tr = 2;
-               tr0_cnt0 = (SZ_64K - BIT(align_to));
-               if (len / tr0_cnt0 >= SZ_64K) {
-                       dev_err(uc->ud->dev, "size %zu is not supported\n",
-                               len);
-                       return NULL;
-               }
-
-               tr0_cnt1 = len / tr0_cnt0;
-               tr1_cnt0 = len % tr0_cnt0;
+       num_tr = udma_get_tr_counters(len, __ffs(src | dest), &tr0_cnt0,
+                                     &tr0_cnt1, &tr1_cnt0);
+       if (num_tr < 0) {
+               dev_err(uc->ud->dev, "size %zu is not supported\n",
+                       len);
+               return NULL;
        }
 
        d = udma_alloc_tr_desc(uc, tr_size, num_tr, DMA_MEM_TO_MEM);
@@ -2631,6 +2767,9 @@ static enum dma_status udma_tx_status(struct dma_chan *chan,
 
        ret = dma_cookie_status(chan, cookie, txstate);
 
+       if (!udma_is_chan_running(uc))
+               ret = DMA_COMPLETE;
+
        if (ret == DMA_IN_PROGRESS && udma_is_chan_paused(uc))
                ret = DMA_PAUSED;
 
@@ -2697,11 +2836,8 @@ static int udma_pause(struct dma_chan *chan)
 {
        struct udma_chan *uc = to_udma_chan(chan);
 
-       if (!uc->desc)
-               return -EINVAL;
-
        /* pause the channel */
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                udma_rchanrt_update_bits(uc->rchan,
                                         UDMA_RCHAN_RT_PEER_RT_EN_REG,
@@ -2730,11 +2866,8 @@ static int udma_resume(struct dma_chan *chan)
 {
        struct udma_chan *uc = to_udma_chan(chan);
 
-       if (!uc->desc)
-               return -EINVAL;
-
        /* resume the channel */
-       switch (uc->desc->dir) {
+       switch (uc->config.dir) {
        case DMA_DEV_TO_MEM:
                udma_rchanrt_update_bits(uc->rchan,
                                         UDMA_RCHAN_RT_PEER_RT_EN_REG,
@@ -3248,6 +3381,98 @@ static int udma_setup_resources(struct udma_dev *ud)
        return ch_count;
 }
 
+static int udma_setup_rx_flush(struct udma_dev *ud)
+{
+       struct udma_rx_flush *rx_flush = &ud->rx_flush;
+       struct cppi5_desc_hdr_t *tr_desc;
+       struct cppi5_tr_type1_t *tr_req;
+       struct cppi5_host_desc_t *desc;
+       struct device *dev = ud->dev;
+       struct udma_hwdesc *hwdesc;
+       size_t tr_size;
+
+       /* Allocate 1K buffer for discarded data on RX channel teardown */
+       rx_flush->buffer_size = SZ_1K;
+       rx_flush->buffer_vaddr = devm_kzalloc(dev, rx_flush->buffer_size,
+                                             GFP_KERNEL);
+       if (!rx_flush->buffer_vaddr)
+               return -ENOMEM;
+
+       rx_flush->buffer_paddr = dma_map_single(dev, rx_flush->buffer_vaddr,
+                                               rx_flush->buffer_size,
+                                               DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, rx_flush->buffer_paddr))
+               return -ENOMEM;
+
+       /* Set up descriptor to be used for TR mode */
+       hwdesc = &rx_flush->hwdescs[0];
+       tr_size = sizeof(struct cppi5_tr_type1_t);
+       hwdesc->cppi5_desc_size = cppi5_trdesc_calc_size(tr_size, 1);
+       hwdesc->cppi5_desc_size = ALIGN(hwdesc->cppi5_desc_size,
+                                       ud->desc_align);
+
+       hwdesc->cppi5_desc_vaddr = devm_kzalloc(dev, hwdesc->cppi5_desc_size,
+                                               GFP_KERNEL);
+       if (!hwdesc->cppi5_desc_vaddr)
+               return -ENOMEM;
+
+       hwdesc->cppi5_desc_paddr = dma_map_single(dev, hwdesc->cppi5_desc_vaddr,
+                                                 hwdesc->cppi5_desc_size,
+                                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, hwdesc->cppi5_desc_paddr))
+               return -ENOMEM;
+
+       /* Start of the TR req records */
+       hwdesc->tr_req_base = hwdesc->cppi5_desc_vaddr + tr_size;
+       /* Start address of the TR response array */
+       hwdesc->tr_resp_base = hwdesc->tr_req_base + tr_size;
+
+       tr_desc = hwdesc->cppi5_desc_vaddr;
+       cppi5_trdesc_init(tr_desc, 1, tr_size, 0, 0);
+       cppi5_desc_set_pktids(tr_desc, 0, CPPI5_INFO1_DESC_FLOWID_DEFAULT);
+       cppi5_desc_set_retpolicy(tr_desc, 0, 0);
+
+       tr_req = hwdesc->tr_req_base;
+       cppi5_tr_init(&tr_req->flags, CPPI5_TR_TYPE1, false, false,
+                     CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
+       cppi5_tr_csf_set(&tr_req->flags, CPPI5_TR_CSF_SUPR_EVT);
+
+       tr_req->addr = rx_flush->buffer_paddr;
+       tr_req->icnt0 = rx_flush->buffer_size;
+       tr_req->icnt1 = 1;
+
+       /* Set up descriptor to be used for packet mode */
+       hwdesc = &rx_flush->hwdescs[1];
+       hwdesc->cppi5_desc_size = ALIGN(sizeof(struct cppi5_host_desc_t) +
+                                       CPPI5_INFO0_HDESC_EPIB_SIZE +
+                                       CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE,
+                                       ud->desc_align);
+
+       hwdesc->cppi5_desc_vaddr = devm_kzalloc(dev, hwdesc->cppi5_desc_size,
+                                               GFP_KERNEL);
+       if (!hwdesc->cppi5_desc_vaddr)
+               return -ENOMEM;
+
+       hwdesc->cppi5_desc_paddr = dma_map_single(dev, hwdesc->cppi5_desc_vaddr,
+                                                 hwdesc->cppi5_desc_size,
+                                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(dev, hwdesc->cppi5_desc_paddr))
+               return -ENOMEM;
+
+       desc = hwdesc->cppi5_desc_vaddr;
+       cppi5_hdesc_init(desc, 0, 0);
+       cppi5_desc_set_pktids(&desc->hdr, 0, CPPI5_INFO1_DESC_FLOWID_DEFAULT);
+       cppi5_desc_set_retpolicy(&desc->hdr, 0, 0);
+
+       cppi5_hdesc_attach_buf(desc,
+                              rx_flush->buffer_paddr, rx_flush->buffer_size,
+                              rx_flush->buffer_paddr, rx_flush->buffer_size);
+
+       dma_sync_single_for_device(dev, hwdesc->cppi5_desc_paddr,
+                                  hwdesc->cppi5_desc_size, DMA_TO_DEVICE);
+       return 0;
+}
+
 #define TI_UDMAC_BUSWIDTHS     (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
                                 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
                                 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
@@ -3361,6 +3586,10 @@ static int udma_probe(struct platform_device *pdev)
        if (ud->desc_align < dma_get_cache_alignment())
                ud->desc_align = dma_get_cache_alignment();
 
+       ret = udma_setup_rx_flush(ud);
+       if (ret)
+               return ret;
+
        for (i = 0; i < ud->tchan_cnt; i++) {
                struct udma_tchan *tchan = &ud->tchans[i];
 
index 2d26338..880ffd8 100644 (file)
@@ -479,20 +479,14 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p)
                pinf = &p->ceinfo;
                if (!priv->p_data->quirks) {
                        snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "DDR ECC error type:%s Row %d Bank %d Col %d ",
-                                 "CE", pinf->row, pinf->bank, pinf->col);
-                       snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "Bit Position: %d Data: 0x%08x\n",
+                                "DDR ECC error type:%s Row %d Bank %d Col %d Bit Position: %d Data: 0x%08x",
+                                "CE", pinf->row, pinf->bank, pinf->col,
                                 pinf->bitpos, pinf->data);
                } else {
                        snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "DDR ECC error type:%s Row %d Bank %d Col %d ",
-                                 "CE", pinf->row, pinf->bank, pinf->col);
-                       snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "BankGroup Number %d Block Number %d ",
-                                pinf->bankgrpnr, pinf->blknr);
-                       snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "Bit Position: %d Data: 0x%08x\n",
+                                "DDR ECC error type:%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d Bit Position: %d Data: 0x%08x",
+                                "CE", pinf->row, pinf->bank, pinf->col,
+                                pinf->bankgrpnr, pinf->blknr,
                                 pinf->bitpos, pinf->data);
                }
 
@@ -509,10 +503,8 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p)
                                "UE", pinf->row, pinf->bank, pinf->col);
                } else {
                        snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "DDR ECC error type :%s Row %d Bank %d Col %d ",
-                                "UE", pinf->row, pinf->bank, pinf->col);
-                       snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-                                "BankGroup Number %d Block Number %d",
+                                "DDR ECC error type :%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d",
+                                "UE", pinf->row, pinf->bank, pinf->col,
                                 pinf->bankgrpnr, pinf->blknr);
                }
 
index 621220a..21ea99f 100644 (file)
@@ -552,7 +552,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                seed = early_memremap(efi.rng_seed, sizeof(*seed));
                if (seed != NULL) {
-                       size = seed->size;
+                       size = READ_ONCE(seed->size);
                        early_memunmap(seed, sizeof(*seed));
                } else {
                        pr_err("Could not map UEFI random seed!\n");
@@ -562,7 +562,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
                                              sizeof(*seed) + size);
                        if (seed != NULL) {
                                pr_notice("seeding entropy pool\n");
-                               add_bootloader_randomness(seed->bits, seed->size);
+                               add_bootloader_randomness(seed->bits, size);
                                early_memunmap(seed, sizeof(*seed) + size);
                        } else {
                                pr_err("Could not map UEFI random seed!\n");
index 03b43b7..f71eaa5 100644 (file)
@@ -29,6 +29,7 @@ struct imx_sc_chan {
        struct mbox_client cl;
        struct mbox_chan *ch;
        int idx;
+       struct completion tx_done;
 };
 
 struct imx_sc_ipc {
@@ -100,6 +101,14 @@ int imx_scu_get_handle(struct imx_sc_ipc **ipc)
 }
 EXPORT_SYMBOL(imx_scu_get_handle);
 
+/* Callback called when the word of a message is ack-ed, eg read by SCU */
+static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r)
+{
+       struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl);
+
+       complete(&sc_chan->tx_done);
+}
+
 static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
 {
        struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl);
@@ -149,6 +158,19 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
 
        for (i = 0; i < hdr->size; i++) {
                sc_chan = &sc_ipc->chans[i % 4];
+
+               /*
+                * SCU requires that all messages words are written
+                * sequentially but linux MU driver implements multiple
+                * independent channels for each register so ordering between
+                * different channels must be ensured by SCU API interface.
+                *
+                * Wait for tx_done before every send to ensure that no
+                * queueing happens at the mailbox channel level.
+                */
+               wait_for_completion(&sc_chan->tx_done);
+               reinit_completion(&sc_chan->tx_done);
+
                ret = mbox_send_message(sc_chan->ch, &data[i]);
                if (ret < 0)
                        return ret;
@@ -247,6 +269,11 @@ static int imx_scu_probe(struct platform_device *pdev)
                cl->knows_txdone = true;
                cl->rx_callback = imx_scu_rx_callback;
 
+               /* Initial tx_done completion as "done" */
+               cl->tx_done = imx_scu_tx_done;
+               init_completion(&sc_chan->tx_done);
+               complete(&sc_chan->tx_done);
+
                sc_chan->sc_ipc = sc_ipc;
                sc_chan->idx = i % 4;
                sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
index 4b56a58..d073cb3 100644 (file)
@@ -16,7 +16,7 @@ struct imx_sc_msg_req_misc_set_ctrl {
        u32 ctrl;
        u32 val;
        u16 resource;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_cpu_start {
        struct imx_sc_rpc_msg hdr;
@@ -24,18 +24,18 @@ struct imx_sc_msg_req_cpu_start {
        u32 address_lo;
        u16 resource;
        u8 enable;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_misc_get_ctrl {
        struct imx_sc_rpc_msg hdr;
        u32 ctrl;
        u16 resource;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_resp_misc_get_ctrl {
        struct imx_sc_rpc_msg hdr;
        u32 val;
-} __packed;
+} __packed __aligned(4);
 
 /*
  * This function sets a miscellaneous control value.
index b556612..af3ae00 100644 (file)
@@ -61,7 +61,7 @@ struct imx_sc_msg_req_set_resource_power_mode {
        struct imx_sc_rpc_msg hdr;
        u16 resource;
        u8 mode;
-} __packed;
+} __packed __aligned(4);
 
 #define IMX_SCU_PD_NAME_SIZE 20
 struct imx_sc_pm_domain {
index 94e2fd7..42f4feb 100644 (file)
@@ -1389,7 +1389,7 @@ amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_ATOMIC |
+           DRIVER_ATOMIC |
            DRIVER_GEM |
            DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
            DRIVER_SYNCOBJ_TIMELINE,
index d3c27a3..7546da0 100644 (file)
@@ -195,6 +195,7 @@ struct amdgpu_gmc {
        uint32_t                srbm_soft_reset;
        bool                    prt_warning;
        uint64_t                stolen_size;
+       uint32_t                sdpif_register;
        /* apertures */
        u64                     shared_aperture_start;
        u64                     shared_aperture_end;
index 22bbb36..0270259 100644 (file)
@@ -52,7 +52,7 @@
  * 1. Primary ring
  * 2. Async ring
  */
-#define GFX10_NUM_GFX_RINGS    2
+#define GFX10_NUM_GFX_RINGS_NV1X       1
 #define GFX10_MEC_HPD_SIZE     2048
 
 #define F32_CE_PROGRAM_RAM_SIZE                65536
@@ -1304,7 +1304,7 @@ static int gfx_v10_0_sw_init(void *handle)
        case CHIP_NAVI14:
        case CHIP_NAVI12:
                adev->gfx.me.num_me = 1;
-               adev->gfx.me.num_pipe_per_me = 2;
+               adev->gfx.me.num_pipe_per_me = 1;
                adev->gfx.me.num_queue_per_pipe = 1;
                adev->gfx.mec.num_mec = 2;
                adev->gfx.mec.num_pipe_per_mec = 4;
@@ -2710,18 +2710,20 @@ static int gfx_v10_0_cp_gfx_start(struct amdgpu_device *adev)
        amdgpu_ring_commit(ring);
 
        /* submit cs packet to copy state 0 to next available state */
-       ring = &adev->gfx.gfx_ring[1];
-       r = amdgpu_ring_alloc(ring, 2);
-       if (r) {
-               DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r);
-               return r;
-       }
-
-       amdgpu_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
-       amdgpu_ring_write(ring, 0);
+       if (adev->gfx.num_gfx_rings > 1) {
+               /* maximum supported gfx ring is 2 */
+               ring = &adev->gfx.gfx_ring[1];
+               r = amdgpu_ring_alloc(ring, 2);
+               if (r) {
+                       DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r);
+                       return r;
+               }
 
-       amdgpu_ring_commit(ring);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
+               amdgpu_ring_write(ring, 0);
 
+               amdgpu_ring_commit(ring);
+       }
        return 0;
 }
 
@@ -2818,39 +2820,41 @@ static int gfx_v10_0_cp_gfx_resume(struct amdgpu_device *adev)
        mutex_unlock(&adev->srbm_mutex);
 
        /* Init gfx ring 1 for pipe 1 */
-       mutex_lock(&adev->srbm_mutex);
-       gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID1);
-       ring = &adev->gfx.gfx_ring[1];
-       rb_bufsz = order_base_2(ring->ring_size / 8);
-       tmp = REG_SET_FIELD(0, CP_RB1_CNTL, RB_BUFSZ, rb_bufsz);
-       tmp = REG_SET_FIELD(tmp, CP_RB1_CNTL, RB_BLKSZ, rb_bufsz - 2);
-       WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
-       /* Initialize the ring buffer's write pointers */
-       ring->wptr = 0;
-       WREG32_SOC15(GC, 0, mmCP_RB1_WPTR, lower_32_bits(ring->wptr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_WPTR_HI, upper_32_bits(ring->wptr));
-       /* Set the wb address wether it's enabled or not */
-       rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-       WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) &
-               CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
-       wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
-       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO,
-               lower_32_bits(wptr_gpu_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI,
-               upper_32_bits(wptr_gpu_addr));
-
-       mdelay(1);
-       WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
-
-       rb_addr = ring->gpu_addr >> 8;
-       WREG32_SOC15(GC, 0, mmCP_RB1_BASE, rb_addr);
-       WREG32_SOC15(GC, 0, mmCP_RB1_BASE_HI, upper_32_bits(rb_addr));
-       WREG32_SOC15(GC, 0, mmCP_RB1_ACTIVE, 1);
-
-       gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
-       mutex_unlock(&adev->srbm_mutex);
-
+       if (adev->gfx.num_gfx_rings > 1) {
+               mutex_lock(&adev->srbm_mutex);
+               gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID1);
+               /* maximum supported gfx ring is 2 */
+               ring = &adev->gfx.gfx_ring[1];
+               rb_bufsz = order_base_2(ring->ring_size / 8);
+               tmp = REG_SET_FIELD(0, CP_RB1_CNTL, RB_BUFSZ, rb_bufsz);
+               tmp = REG_SET_FIELD(tmp, CP_RB1_CNTL, RB_BLKSZ, rb_bufsz - 2);
+               WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
+               /* Initialize the ring buffer's write pointers */
+               ring->wptr = 0;
+               WREG32_SOC15(GC, 0, mmCP_RB1_WPTR, lower_32_bits(ring->wptr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_WPTR_HI, upper_32_bits(ring->wptr));
+               /* Set the wb address wether it's enabled or not */
+               rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
+               WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) &
+                            CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
+               wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+               WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO,
+                            lower_32_bits(wptr_gpu_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI,
+                            upper_32_bits(wptr_gpu_addr));
+
+               mdelay(1);
+               WREG32_SOC15(GC, 0, mmCP_RB1_CNTL, tmp);
+
+               rb_addr = ring->gpu_addr >> 8;
+               WREG32_SOC15(GC, 0, mmCP_RB1_BASE, rb_addr);
+               WREG32_SOC15(GC, 0, mmCP_RB1_BASE_HI, upper_32_bits(rb_addr));
+               WREG32_SOC15(GC, 0, mmCP_RB1_ACTIVE, 1);
+
+               gfx_v10_0_cp_gfx_set_doorbell(adev, ring);
+               mutex_unlock(&adev->srbm_mutex);
+       }
        /* Switch to pipe 0 */
        mutex_lock(&adev->srbm_mutex);
        gfx_v10_0_cp_gfx_switch_pipe(adev, PIPE_ID0);
@@ -3513,6 +3517,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring)
 
                /* reset ring buffer */
                ring->wptr = 0;
+               atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
                amdgpu_ring_clear_ring(ring);
        } else {
                amdgpu_ring_clear_ring(ring);
@@ -3966,7 +3971,8 @@ static int gfx_v10_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS;
+       adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X;
+
        adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS;
 
        gfx_v10_0_set_kiq_pm4_funcs(adev);
index 3afdbbd..889154a 100644 (file)
@@ -3663,6 +3663,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
 
                /* reset ring buffer */
                ring->wptr = 0;
+               atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
                amdgpu_ring_clear_ring(ring);
        } else {
                amdgpu_ring_clear_ring(ring);
index 90216ab..cc0c273 100644 (file)
@@ -1272,6 +1272,19 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
 }
 
 /**
+ * gmc_v9_0_restore_registers - restores regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This restores register values, saved at suspend.
+ */
+static void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
+}
+
+/**
  * gmc_v9_0_gart_enable - gart enable
  *
  * @adev: amdgpu_device pointer
@@ -1377,6 +1390,20 @@ static int gmc_v9_0_hw_init(void *handle)
 }
 
 /**
+ * gmc_v9_0_save_registers - saves regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This saves potential register values that should be
+ * restored upon resume
+ */
+static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
+{
+       if (adev->asic_type == CHIP_RAVEN)
+               adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
+}
+
+/**
  * gmc_v9_0_gart_disable - gart disable
  *
  * @adev: amdgpu_device pointer
@@ -1412,9 +1439,16 @@ static int gmc_v9_0_hw_fini(void *handle)
 
 static int gmc_v9_0_suspend(void *handle)
 {
+       int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       return gmc_v9_0_hw_fini(adev);
+       r = gmc_v9_0_hw_fini(adev);
+       if (r)
+               return r;
+
+       gmc_v9_0_save_registers(adev);
+
+       return 0;
 }
 
 static int gmc_v9_0_resume(void *handle)
@@ -1422,6 +1456,7 @@ static int gmc_v9_0_resume(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       gmc_v9_0_restore_registers(adev);
        r = gmc_v9_0_hw_init(adev);
        if (r)
                return r;
index 2b488df..d8945c3 100644 (file)
 #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK  0x00010000L
 #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK            0x00020000L
 #define mmHDP_MEM_POWER_CTRL_BASE_IDX  0
+
+/* for Vega20/arcturus regiter offset change */
+#define        mmROM_INDEX_VG20                                0x00e4
+#define        mmROM_INDEX_VG20_BASE_IDX                       0
+#define        mmROM_DATA_VG20                                 0x00e5
+#define        mmROM_DATA_VG20_BASE_IDX                        0
+
 /*
  * Indirect registers accessor
  */
@@ -309,6 +316,8 @@ static bool soc15_read_bios_from_rom(struct amdgpu_device *adev,
 {
        u32 *dw_ptr;
        u32 i, length_dw;
+       uint32_t rom_index_offset;
+       uint32_t rom_data_offset;
 
        if (bios == NULL)
                return false;
@@ -321,11 +330,23 @@ static bool soc15_read_bios_from_rom(struct amdgpu_device *adev,
        dw_ptr = (u32 *)bios;
        length_dw = ALIGN(length_bytes, 4) / 4;
 
+       switch (adev->asic_type) {
+       case CHIP_VEGA20:
+       case CHIP_ARCTURUS:
+               rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX_VG20);
+               rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA_VG20);
+               break;
+       default:
+               rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX);
+               rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA);
+               break;
+       }
+
        /* set rom index to 0 */
-       WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX), 0);
+       WREG32(rom_index_offset, 0);
        /* read out the rom data */
        for (i = 0; i < length_dw; i++)
-               dw_ptr[i] = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA));
+               dw_ptr[i] = RREG32(rom_data_offset);
 
        return true;
 }
index e8f66fb..e997251 100644 (file)
@@ -1422,6 +1422,73 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
                drm_kms_helper_hotplug_event(dev);
 }
 
+static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
+{
+       struct smu_context *smu = &adev->smu;
+       int ret = 0;
+
+       if (!is_support_sw_smu(adev))
+               return 0;
+
+       /* This interface is for dGPU Navi1x.Linux dc-pplib interface depends
+        * on window driver dc implementation.
+        * For Navi1x, clock settings of dcn watermarks are fixed. the settings
+        * should be passed to smu during boot up and resume from s3.
+        * boot up: dc calculate dcn watermark clock settings within dc_create,
+        * dcn20_resource_construct
+        * then call pplib functions below to pass the settings to smu:
+        * smu_set_watermarks_for_clock_ranges
+        * smu_set_watermarks_table
+        * navi10_set_watermarks_table
+        * smu_write_watermarks_table
+        *
+        * For Renoir, clock settings of dcn watermark are also fixed values.
+        * dc has implemented different flow for window driver:
+        * dc_hardware_init / dc_set_power_state
+        * dcn10_init_hw
+        * notify_wm_ranges
+        * set_wm_ranges
+        * -- Linux
+        * smu_set_watermarks_for_clock_ranges
+        * renoir_set_watermarks_table
+        * smu_write_watermarks_table
+        *
+        * For Linux,
+        * dc_hardware_init -> amdgpu_dm_init
+        * dc_set_power_state --> dm_resume
+        *
+        * therefore, this function apply to navi10/12/14 but not Renoir
+        * *
+        */
+       switch(adev->asic_type) {
+       case CHIP_NAVI10:
+       case CHIP_NAVI14:
+       case CHIP_NAVI12:
+               break;
+       default:
+               return 0;
+       }
+
+       mutex_lock(&smu->mutex);
+
+       /* pass data to smu controller */
+       if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
+                       !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+               ret = smu_write_watermarks_table(smu);
+
+               if (ret) {
+                       mutex_unlock(&smu->mutex);
+                       DRM_ERROR("Failed to update WMTABLE!\n");
+                       return ret;
+               }
+               smu->watermarks_bitmap |= WATERMARKS_LOADED;
+       }
+
+       mutex_unlock(&smu->mutex);
+
+       return 0;
+}
+
 /**
  * dm_hw_init() - Initialize DC device
  * @handle: The base driver device containing the amdgpu_dm device.
@@ -1700,6 +1767,8 @@ static int dm_resume(void *handle)
 
        amdgpu_dm_irq_resume_late(adev);
 
+       amdgpu_dm_smu_write_watermarks_table(adev);
+
        return 0;
 }
 
index 5672f77..da73161 100644 (file)
@@ -451,6 +451,7 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                                           aconnector->dc_sink);
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
+               aconnector->dc_link->cur_link_settings.lane_count = 0;
        }
 
        drm_connector_unregister(connector);
index f36a0d8..446ba0a 100644 (file)
@@ -840,8 +840,8 @@ static void hubbub1_det_request_size(
 
        hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
 
-       swath_bytes_horz_wc = height * blk256_height * bpe;
-       swath_bytes_vert_wc = width * blk256_width * bpe;
+       swath_bytes_horz_wc = width * blk256_height * bpe;
+       swath_bytes_vert_wc = height * blk256_width * bpe;
 
        *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
                        false : /* full 256B request */
index 85f90f3..e310d67 100644 (file)
@@ -335,6 +335,117 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = {
        .use_urgent_burst_bw = 0
 };
 
+struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {
+       .clock_limits = {
+                       {
+                               .state = 0,
+                               .dcfclk_mhz = 560.0,
+                               .fabricclk_mhz = 560.0,
+                               .dispclk_mhz = 513.0,
+                               .dppclk_mhz = 513.0,
+                               .phyclk_mhz = 540.0,
+                               .socclk_mhz = 560.0,
+                               .dscclk_mhz = 171.0,
+                               .dram_speed_mts = 8960.0,
+                       },
+                       {
+                               .state = 1,
+                               .dcfclk_mhz = 694.0,
+                               .fabricclk_mhz = 694.0,
+                               .dispclk_mhz = 642.0,
+                               .dppclk_mhz = 642.0,
+                               .phyclk_mhz = 600.0,
+                               .socclk_mhz = 694.0,
+                               .dscclk_mhz = 214.0,
+                               .dram_speed_mts = 11104.0,
+                       },
+                       {
+                               .state = 2,
+                               .dcfclk_mhz = 875.0,
+                               .fabricclk_mhz = 875.0,
+                               .dispclk_mhz = 734.0,
+                               .dppclk_mhz = 734.0,
+                               .phyclk_mhz = 810.0,
+                               .socclk_mhz = 875.0,
+                               .dscclk_mhz = 245.0,
+                               .dram_speed_mts = 14000.0,
+                       },
+                       {
+                               .state = 3,
+                               .dcfclk_mhz = 1000.0,
+                               .fabricclk_mhz = 1000.0,
+                               .dispclk_mhz = 1100.0,
+                               .dppclk_mhz = 1100.0,
+                               .phyclk_mhz = 810.0,
+                               .socclk_mhz = 1000.0,
+                               .dscclk_mhz = 367.0,
+                               .dram_speed_mts = 16000.0,
+                       },
+                       {
+                               .state = 4,
+                               .dcfclk_mhz = 1200.0,
+                               .fabricclk_mhz = 1200.0,
+                               .dispclk_mhz = 1284.0,
+                               .dppclk_mhz = 1284.0,
+                               .phyclk_mhz = 810.0,
+                               .socclk_mhz = 1200.0,
+                               .dscclk_mhz = 428.0,
+                               .dram_speed_mts = 16000.0,
+                       },
+                       /*Extra state, no dispclk ramping*/
+                       {
+                               .state = 5,
+                               .dcfclk_mhz = 1200.0,
+                               .fabricclk_mhz = 1200.0,
+                               .dispclk_mhz = 1284.0,
+                               .dppclk_mhz = 1284.0,
+                               .phyclk_mhz = 810.0,
+                               .socclk_mhz = 1200.0,
+                               .dscclk_mhz = 428.0,
+                               .dram_speed_mts = 16000.0,
+                       },
+               },
+       .num_states = 5,
+       .sr_exit_time_us = 8.6,
+       .sr_enter_plus_exit_time_us = 10.9,
+       .urgent_latency_us = 4.0,
+       .urgent_latency_pixel_data_only_us = 4.0,
+       .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
+       .urgent_latency_vm_data_only_us = 4.0,
+       .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+       .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+       .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+       .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
+       .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
+       .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
+       .max_avg_sdp_bw_use_normal_percent = 40.0,
+       .max_avg_dram_bw_use_normal_percent = 40.0,
+       .writeback_latency_us = 12.0,
+       .ideal_dram_bw_after_urgent_percent = 40.0,
+       .max_request_size_bytes = 256,
+       .dram_channel_width_bytes = 2,
+       .fabric_datapath_to_dcn_data_return_bytes = 64,
+       .dcn_downspread_percent = 0.5,
+       .downspread_percent = 0.38,
+       .dram_page_open_time_ns = 50.0,
+       .dram_rw_turnaround_time_ns = 17.5,
+       .dram_return_buffer_per_channel_bytes = 8192,
+       .round_trip_ping_latency_dcfclk_cycles = 131,
+       .urgent_out_of_order_return_per_channel_bytes = 256,
+       .channel_interleave_bytes = 256,
+       .num_banks = 8,
+       .num_chans = 8,
+       .vmm_page_size_bytes = 4096,
+       .dram_clock_change_latency_us = 404.0,
+       .dummy_pstate_latency_us = 5.0,
+       .writeback_dram_clock_change_latency_us = 23.0,
+       .return_bus_width_bytes = 64,
+       .dispclk_dppclk_vco_speed_mhz = 3850,
+       .xfc_bus_transport_time_us = 20,
+       .xfc_xbuf_latency_tolerance_us = 4,
+       .use_urgent_burst_bw = 0
+};
+
 struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 };
 
 #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
@@ -3291,6 +3402,9 @@ void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st
 static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb(
        uint32_t hw_internal_rev)
 {
+       if (ASICREV_IS_NAVI14_M(hw_internal_rev))
+               return &dcn2_0_nv14_soc;
+
        if (ASICREV_IS_NAVI12_P(hw_internal_rev))
                return &dcn2_0_nv12_soc;
 
index b6f74bf..27bb8c1 100644 (file)
 #define mmCRTC4_CRTC_DRR_CONTROL                                                                       0x0f3e
 #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX                                                              2
 
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0                                                                  0x395d
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX                                                         2
 
 // addressBlock: dce_dc_fmt4_dispdec
 // base address: 0x2000
index 99ad4dd..96e81c7 100644 (file)
@@ -222,7 +222,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type,
 {
        int ret = 0;
 
-       if (min <= 0 && max <= 0)
+       if (min < 0 && max < 0)
                return -EINVAL;
 
        if (!smu_clk_dpm_is_enabled(smu, clk_type))
@@ -2006,8 +2006,11 @@ int smu_set_watermarks_for_clock_ranges(struct smu_context *smu,
                        smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
                        smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
                smu_set_watermarks_table(smu, table, clock_ranges);
-               smu->watermarks_bitmap |= WATERMARKS_EXIST;
-               smu->watermarks_bitmap &= ~WATERMARKS_LOADED;
+
+               if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) {
+                       smu->watermarks_bitmap |= WATERMARKS_EXIST;
+                       smu->watermarks_bitmap &= ~WATERMARKS_LOADED;
+               }
        }
 
        mutex_unlock(&smu->mutex);
index 0d73a49..aed4d6e 100644 (file)
@@ -1063,15 +1063,6 @@ static int navi10_display_config_changed(struct smu_context *smu)
        int ret = 0;
 
        if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
-           !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
-               ret = smu_write_watermarks_table(smu);
-               if (ret)
-                       return ret;
-
-               smu->watermarks_bitmap |= WATERMARKS_LOADED;
-       }
-
-       if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
            smu_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) &&
            smu_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
                ret = smu_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays,
@@ -1493,6 +1484,7 @@ static int navi10_set_watermarks_table(struct smu_context *smu,
                                       *clock_ranges)
 {
        int i;
+       int ret = 0;
        Watermarks_t *table = watermarks;
 
        if (!table || !clock_ranges)
@@ -1544,6 +1536,18 @@ static int navi10_set_watermarks_table(struct smu_context *smu,
                                clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
        }
 
+       smu->watermarks_bitmap |= WATERMARKS_EXIST;
+
+       /* pass data to smu controller */
+       if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+               ret = smu_write_watermarks_table(smu);
+               if (ret) {
+                       pr_err("Failed to update WMTABLE!");
+                       return ret;
+               }
+               smu->watermarks_bitmap |= WATERMARKS_LOADED;
+       }
+
        return 0;
 }
 
index 861e641..3ad0f4a 100644 (file)
@@ -111,8 +111,8 @@ static struct smu_12_0_cmn2aisc_mapping renoir_clk_map[SMU_CLK_COUNT] = {
        CLK_MAP(GFXCLK, CLOCK_GFXCLK),
        CLK_MAP(SCLK,   CLOCK_GFXCLK),
        CLK_MAP(SOCCLK, CLOCK_SOCCLK),
-       CLK_MAP(UCLK, CLOCK_UMCCLK),
-       CLK_MAP(MCLK, CLOCK_UMCCLK),
+       CLK_MAP(UCLK, CLOCK_FCLK),
+       CLK_MAP(MCLK, CLOCK_FCLK),
 };
 
 static struct smu_12_0_cmn2aisc_mapping renoir_table_map[SMU_TABLE_COUNT] = {
@@ -280,7 +280,7 @@ static int renoir_print_clk_levels(struct smu_context *smu,
                break;
        case SMU_MCLK:
                count = NUM_MEMCLK_DPM_LEVELS;
-               cur_value = metrics.ClockFrequency[CLOCK_UMCCLK];
+               cur_value = metrics.ClockFrequency[CLOCK_FCLK];
                break;
        case SMU_DCEFCLK:
                count = NUM_DCFCLK_DPM_LEVELS;
@@ -806,9 +806,10 @@ static int renoir_set_watermarks_table(
                                clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
        }
 
+       smu->watermarks_bitmap |= WATERMARKS_EXIST;
+
        /* pass data to smu controller */
-       if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
-                       !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+       if (!(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
                ret = smu_write_watermarks_table(smu);
                if (ret) {
                        pr_err("Failed to update WMTABLE!");
index b06c057..c9e5ce1 100644 (file)
@@ -978,8 +978,12 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
        struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
        int ret = 0;
 
-       max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
+       if (!smu->smu_table.max_sustainable_clocks)
+               max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
                                         GFP_KERNEL);
+       else
+               max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
+
        smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
 
        max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
index 870e6db..518e659 100644 (file)
@@ -458,9 +458,6 @@ int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_
 {
        int ret = 0;
 
-       if (max < min)
-               return -EINVAL;
-
        switch (clk_type) {
        case SMU_GFXCLK:
        case SMU_SCLK:
index 56f55c5..2dfa2fd 100644 (file)
@@ -210,8 +210,7 @@ static int anx6345_dp_link_training(struct anx6345 *anx6345)
        if (err)
                return err;
 
-       dpcd[0] = drm_dp_max_link_rate(anx6345->dpcd);
-       dpcd[0] = drm_dp_link_rate_to_bw_code(dpcd[0]);
+       dpcd[0] = dp_bw;
        err = regmap_write(anx6345->map[I2C_IDX_DPTX],
                           SP_DP_MAIN_LINK_BW_SET_REG, dpcd[0]);
        if (err)
index cce0b1b..ed0fea2 100644 (file)
@@ -1935,7 +1935,7 @@ static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
        return parent_lct + 1;
 }
 
-static bool drm_dp_mst_is_dp_mst_end_device(u8 pdt, bool mcs)
+static bool drm_dp_mst_is_end_device(u8 pdt, bool mcs)
 {
        switch (pdt) {
        case DP_PEER_DEVICE_DP_LEGACY_CONV:
@@ -1965,13 +1965,13 @@ drm_dp_port_set_pdt(struct drm_dp_mst_port *port, u8 new_pdt,
 
        /* Teardown the old pdt, if there is one */
        if (port->pdt != DP_PEER_DEVICE_NONE) {
-               if (drm_dp_mst_is_dp_mst_end_device(port->pdt, port->mcs)) {
+               if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
                        /*
                         * If the new PDT would also have an i2c bus,
                         * don't bother with reregistering it
                         */
                        if (new_pdt != DP_PEER_DEVICE_NONE &&
-                           drm_dp_mst_is_dp_mst_end_device(new_pdt, new_mcs)) {
+                           drm_dp_mst_is_end_device(new_pdt, new_mcs)) {
                                port->pdt = new_pdt;
                                port->mcs = new_mcs;
                                return 0;
@@ -1991,7 +1991,7 @@ drm_dp_port_set_pdt(struct drm_dp_mst_port *port, u8 new_pdt,
        port->mcs = new_mcs;
 
        if (port->pdt != DP_PEER_DEVICE_NONE) {
-               if (drm_dp_mst_is_dp_mst_end_device(port->pdt, port->mcs)) {
+               if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
                        /* add i2c over sideband */
                        ret = drm_dp_mst_register_i2c_bus(&port->aux);
                } else {
@@ -2172,7 +2172,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb,
        }
 
        if (port->pdt != DP_PEER_DEVICE_NONE &&
-           drm_dp_mst_is_dp_mst_end_device(port->pdt, port->mcs)) {
+           drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
                port->cached_edid = drm_get_edid(port->connector,
                                                 &port->aux.ddc);
                drm_connector_set_tile_property(port->connector);
@@ -2302,14 +2302,18 @@ drm_dp_mst_handle_link_address_port(struct drm_dp_mst_branch *mstb,
                mutex_unlock(&mgr->lock);
        }
 
-       if (old_ddps != port->ddps) {
-               if (port->ddps) {
-                       if (!port->input) {
-                               drm_dp_send_enum_path_resources(mgr, mstb,
-                                                               port);
-                       }
+       /*
+        * Reprobe PBN caps on both hotplug, and when re-probing the link
+        * for our parent mstb
+        */
+       if (old_ddps != port->ddps || !created) {
+               if (port->ddps && !port->input) {
+                       ret = drm_dp_send_enum_path_resources(mgr, mstb,
+                                                             port);
+                       if (ret == 1)
+                               changed = true;
                } else {
-                       port->available_pbn = 0;
+                       port->full_pbn = 0;
                }
        }
 
@@ -2401,11 +2405,10 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
        port->ddps = conn_stat->displayport_device_plug_status;
 
        if (old_ddps != port->ddps) {
-               if (port->ddps) {
-                       dowork = true;
-               } else {
-                       port->available_pbn = 0;
-               }
+               if (port->ddps && !port->input)
+                       drm_dp_send_enum_path_resources(mgr, mstb, port);
+               else
+                       port->full_pbn = 0;
        }
 
        new_pdt = port->input ? DP_PEER_DEVICE_NONE : conn_stat->peer_device_type;
@@ -2556,13 +2559,6 @@ static int drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mg
                if (port->input || !port->ddps)
                        continue;
 
-               if (!port->available_pbn) {
-                       drm_modeset_lock(&mgr->base.lock, NULL);
-                       drm_dp_send_enum_path_resources(mgr, mstb, port);
-                       drm_modeset_unlock(&mgr->base.lock);
-                       changed = true;
-               }
-
                if (port->mstb)
                        mstb_child = drm_dp_mst_topology_get_mstb_validated(
                            mgr, port->mstb);
@@ -2990,6 +2986,7 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
 
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
        if (ret > 0) {
+               ret = 0;
                path_res = &txmsg->reply.u.path_resources;
 
                if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {
@@ -3002,14 +2999,22 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
                                      path_res->port_number,
                                      path_res->full_payload_bw_number,
                                      path_res->avail_payload_bw_number);
-                       port->available_pbn =
-                               path_res->avail_payload_bw_number;
+
+                       /*
+                        * If something changed, make sure we send a
+                        * hotplug
+                        */
+                       if (port->full_pbn != path_res->full_payload_bw_number ||
+                           port->fec_capable != path_res->fec_capable)
+                               ret = 1;
+
+                       port->full_pbn = path_res->full_payload_bw_number;
                        port->fec_capable = path_res->fec_capable;
                }
        }
 
        kfree(txmsg);
-       return 0;
+       return ret;
 }
 
 static struct drm_dp_mst_port *drm_dp_get_last_connected_port_to_mstb(struct drm_dp_mst_branch *mstb)
@@ -3596,13 +3601,9 @@ drm_dp_mst_topology_mgr_invalidate_mstb(struct drm_dp_mst_branch *mstb)
        /* The link address will need to be re-sent on resume */
        mstb->link_address_sent = false;
 
-       list_for_each_entry(port, &mstb->ports, next) {
-               /* The PBN for each port will also need to be re-probed */
-               port->available_pbn = 0;
-
+       list_for_each_entry(port, &mstb->ports, next)
                if (port->mstb)
                        drm_dp_mst_topology_mgr_invalidate_mstb(port->mstb);
-       }
 }
 
 /**
@@ -4829,41 +4830,102 @@ static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port,
        return false;
 }
 
-static inline
-int drm_dp_mst_atomic_check_bw_limit(struct drm_dp_mst_branch *branch,
-                                    struct drm_dp_mst_topology_state *mst_state)
+static int
+drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
+                                     struct drm_dp_mst_topology_state *state);
+
+static int
+drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
+                                     struct drm_dp_mst_topology_state *state)
 {
-       struct drm_dp_mst_port *port;
        struct drm_dp_vcpi_allocation *vcpi;
-       int pbn_limit = 0, pbn_used = 0;
+       struct drm_dp_mst_port *port;
+       int pbn_used = 0, ret;
+       bool found = false;
 
-       list_for_each_entry(port, &branch->ports, next) {
-               if (port->mstb)
-                       if (drm_dp_mst_atomic_check_bw_limit(port->mstb, mst_state))
-                               return -ENOSPC;
+       /* Check that we have at least one port in our state that's downstream
+        * of this branch, otherwise we can skip this branch
+        */
+       list_for_each_entry(vcpi, &state->vcpis, next) {
+               if (!vcpi->pbn ||
+                   !drm_dp_mst_port_downstream_of_branch(vcpi->port, mstb))
+                       continue;
 
-               if (port->available_pbn > 0)
-                       pbn_limit = port->available_pbn;
+               found = true;
+               break;
        }
-       DRM_DEBUG_ATOMIC("[MST BRANCH:%p] branch has %d PBN available\n",
-                        branch, pbn_limit);
+       if (!found)
+               return 0;
 
-       list_for_each_entry(vcpi, &mst_state->vcpis, next) {
-               if (!vcpi->pbn)
-                       continue;
+       if (mstb->port_parent)
+               DRM_DEBUG_ATOMIC("[MSTB:%p] [MST PORT:%p] Checking bandwidth limits on [MSTB:%p]\n",
+                                mstb->port_parent->parent, mstb->port_parent,
+                                mstb);
+       else
+               DRM_DEBUG_ATOMIC("[MSTB:%p] Checking bandwidth limits\n",
+                                mstb);
+
+       list_for_each_entry(port, &mstb->ports, next) {
+               ret = drm_dp_mst_atomic_check_port_bw_limit(port, state);
+               if (ret < 0)
+                       return ret;
 
-               if (drm_dp_mst_port_downstream_of_branch(vcpi->port, branch))
-                       pbn_used += vcpi->pbn;
+               pbn_used += ret;
        }
-       DRM_DEBUG_ATOMIC("[MST BRANCH:%p] branch used %d PBN\n",
-                        branch, pbn_used);
 
-       if (pbn_used > pbn_limit) {
-               DRM_DEBUG_ATOMIC("[MST BRANCH:%p] No available bandwidth\n",
-                                branch);
+       return pbn_used;
+}
+
+static int
+drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
+                                     struct drm_dp_mst_topology_state *state)
+{
+       struct drm_dp_vcpi_allocation *vcpi;
+       int pbn_used = 0;
+
+       if (port->pdt == DP_PEER_DEVICE_NONE)
+               return 0;
+
+       if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
+               bool found = false;
+
+               list_for_each_entry(vcpi, &state->vcpis, next) {
+                       if (vcpi->port != port)
+                               continue;
+                       if (!vcpi->pbn)
+                               return 0;
+
+                       found = true;
+                       break;
+               }
+               if (!found)
+                       return 0;
+
+               /* This should never happen, as it means we tried to
+                * set a mode before querying the full_pbn
+                */
+               if (WARN_ON(!port->full_pbn))
+                       return -EINVAL;
+
+               pbn_used = vcpi->pbn;
+       } else {
+               pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
+                                                                state);
+               if (pbn_used <= 0)
+                       return pbn_used;
+       }
+
+       if (pbn_used > port->full_pbn) {
+               DRM_DEBUG_ATOMIC("[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n",
+                                port->parent, port, pbn_used,
+                                port->full_pbn);
                return -ENOSPC;
        }
-       return 0;
+
+       DRM_DEBUG_ATOMIC("[MSTB:%p] [MST PORT:%p] uses %d out of %d PBN\n",
+                        port->parent, port, pbn_used, port->full_pbn);
+
+       return pbn_used;
 }
 
 static inline int
@@ -5061,9 +5123,15 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state)
                ret = drm_dp_mst_atomic_check_vcpi_alloc_limit(mgr, mst_state);
                if (ret)
                        break;
-               ret = drm_dp_mst_atomic_check_bw_limit(mgr->mst_primary, mst_state);
-               if (ret)
+
+               mutex_lock(&mgr->lock);
+               ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
+                                                           mst_state);
+               mutex_unlock(&mgr->lock);
+               if (ret < 0)
                        break;
+               else
+                       ret = 0;
        }
 
        return ret;
index a421a2e..df31e57 100644 (file)
@@ -254,11 +254,16 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
        if (ret)
                goto err_zero_use;
 
-       if (obj->import_attach)
+       if (obj->import_attach) {
                shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
-       else
+       } else {
+               pgprot_t prot = PAGE_KERNEL;
+
+               if (!shmem->map_cached)
+                       prot = pgprot_writecombine(prot);
                shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
-                                   VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+                                   VM_MAP, prot);
+       }
 
        if (!shmem->vaddr) {
                DRM_DEBUG_KMS("Failed to vmap pages\n");
@@ -540,8 +545,9 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
        }
 
        vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND;
-       vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-       vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
+       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+       if (!shmem->map_cached)
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        vma->vm_ops = &drm_gem_shmem_vm_ops;
 
        return 0;
index 8428ae1..1f79bc2 100644 (file)
@@ -55,6 +55,7 @@ static const char * const decon_clks_name[] = {
 struct decon_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
+       void                            *dma_priv;
        struct exynos_drm_crtc          *crtc;
        struct exynos_drm_plane         planes[WINDOWS_NR];
        struct exynos_drm_plane_config  configs[WINDOWS_NR];
@@ -644,7 +645,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
 
        decon_clear_channels(ctx->crtc);
 
-       return exynos_drm_register_dma(drm_dev, dev);
+       return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static void decon_unbind(struct device *dev, struct device *master, void *data)
@@ -654,7 +655,7 @@ static void decon_unbind(struct device *dev, struct device *master, void *data)
        decon_atomic_disable(ctx->crtc);
 
        /* detach this sub driver from iommu mapping if supported. */
-       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static const struct component_ops decon_component_ops = {
index ff59c64..1eed332 100644 (file)
@@ -40,6 +40,7 @@
 struct decon_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
+       void                            *dma_priv;
        struct exynos_drm_crtc          *crtc;
        struct exynos_drm_plane         planes[WINDOWS_NR];
        struct exynos_drm_plane_config  configs[WINDOWS_NR];
@@ -127,13 +128,13 @@ static int decon_ctx_initialize(struct decon_context *ctx,
 
        decon_clear_channels(ctx->crtc);
 
-       return exynos_drm_register_dma(drm_dev, ctx->dev);
+       return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static void decon_ctx_remove(struct decon_context *ctx)
 {
        /* detach this sub driver from iommu mapping if supported. */
-       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static u32 decon_calc_clkdiv(struct decon_context *ctx,
index 9ebc027..619f814 100644 (file)
@@ -58,7 +58,7 @@ static inline void clear_dma_max_seg_size(struct device *dev)
  * mapping.
  */
 static int drm_iommu_attach_device(struct drm_device *drm_dev,
-                               struct device *subdrv_dev)
+                               struct device *subdrv_dev, void **dma_priv)
 {
        struct exynos_drm_private *priv = drm_dev->dev_private;
        int ret;
@@ -74,7 +74,14 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
                return ret;
 
        if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
-               if (to_dma_iommu_mapping(subdrv_dev))
+               /*
+                * Keep the original DMA mapping of the sub-device and
+                * restore it on Exynos DRM detach, otherwise the DMA
+                * framework considers it as IOMMU-less during the next
+                * probe (in case of deferred probe or modular build)
+                */
+               *dma_priv = to_dma_iommu_mapping(subdrv_dev);
+               if (*dma_priv)
                        arm_iommu_detach_device(subdrv_dev);
 
                ret = arm_iommu_attach_device(subdrv_dev, priv->mapping);
@@ -98,19 +105,21 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev,
  * mapping
  */
 static void drm_iommu_detach_device(struct drm_device *drm_dev,
-                               struct device *subdrv_dev)
+                                   struct device *subdrv_dev, void **dma_priv)
 {
        struct exynos_drm_private *priv = drm_dev->dev_private;
 
-       if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
+       if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
                arm_iommu_detach_device(subdrv_dev);
-       else if (IS_ENABLED(CONFIG_IOMMU_DMA))
+               arm_iommu_attach_device(subdrv_dev, *dma_priv);
+       } else if (IS_ENABLED(CONFIG_IOMMU_DMA))
                iommu_detach_device(priv->mapping, subdrv_dev);
 
        clear_dma_max_seg_size(subdrv_dev);
 }
 
-int exynos_drm_register_dma(struct drm_device *drm, struct device *dev)
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
+                           void **dma_priv)
 {
        struct exynos_drm_private *priv = drm->dev_private;
 
@@ -137,13 +146,14 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev)
                priv->mapping = mapping;
        }
 
-       return drm_iommu_attach_device(drm, dev);
+       return drm_iommu_attach_device(drm, dev, dma_priv);
 }
 
-void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev)
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev,
+                              void **dma_priv)
 {
        if (IS_ENABLED(CONFIG_EXYNOS_IOMMU))
-               drm_iommu_detach_device(drm, dev);
+               drm_iommu_detach_device(drm, dev, dma_priv);
 }
 
 void exynos_drm_cleanup_dma(struct drm_device *drm)
index d4d21d8..6ae9056 100644 (file)
@@ -223,8 +223,10 @@ static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
        return priv->mapping ? true : false;
 }
 
-int exynos_drm_register_dma(struct drm_device *drm, struct device *dev);
-void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev);
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
+                           void **dma_priv);
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev,
+                              void **dma_priv);
 void exynos_drm_cleanup_dma(struct drm_device *drm);
 
 #ifdef CONFIG_DRM_EXYNOS_DPI
index 33628d8..a85365c 100644 (file)
@@ -1773,8 +1773,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies),
                                      dsi->supplies);
        if (ret) {
-               dev_info(dev, "failed to get regulators: %d\n", ret);
-               return -EPROBE_DEFER;
+               if (ret != -EPROBE_DEFER)
+                       dev_info(dev, "failed to get regulators: %d\n", ret);
+               return ret;
        }
 
        dsi->clks = devm_kcalloc(dev,
@@ -1787,9 +1788,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
                dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
                if (IS_ERR(dsi->clks[i])) {
                        if (strcmp(clk_names[i], "sclk_mipi") == 0) {
-                               strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME);
-                               i--;
-                               continue;
+                               dsi->clks[i] = devm_clk_get(dev,
+                                                       OLD_SCLK_MIPI_CLK_NAME);
+                               if (!IS_ERR(dsi->clks[i]))
+                                       continue;
                        }
 
                        dev_info(dev, "failed to get the clock: %s\n",
index 8ea2e1d..29ab8be 100644 (file)
@@ -97,6 +97,7 @@ struct fimc_scaler {
 struct fimc_context {
        struct exynos_drm_ipp ipp;
        struct drm_device *drm_dev;
+       void            *dma_priv;
        struct device   *dev;
        struct exynos_drm_ipp_task      *task;
        struct exynos_drm_ipp_formats   *formats;
@@ -1133,7 +1134,7 @@ static int fimc_bind(struct device *dev, struct device *master, void *data)
 
        ctx->drm_dev = drm_dev;
        ipp->drm_dev = drm_dev;
-       exynos_drm_register_dma(drm_dev, dev);
+       exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 
        exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
                        DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -1153,7 +1154,7 @@ static void fimc_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &ctx->ipp;
 
        exynos_drm_ipp_unregister(dev, ipp);
-       exynos_drm_unregister_dma(drm_dev, dev);
+       exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static const struct component_ops fimc_component_ops = {
index 21aec38..bb67cad 100644 (file)
@@ -167,6 +167,7 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = {
 struct fimd_context {
        struct device                   *dev;
        struct drm_device               *drm_dev;
+       void                            *dma_priv;
        struct exynos_drm_crtc          *crtc;
        struct exynos_drm_plane         planes[WINDOWS_NR];
        struct exynos_drm_plane_config  configs[WINDOWS_NR];
@@ -1090,7 +1091,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
        if (is_drm_iommu_supported(drm_dev))
                fimd_clear_channels(ctx->crtc);
 
-       return exynos_drm_register_dma(drm_dev, dev);
+       return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static void fimd_unbind(struct device *dev, struct device *master,
@@ -1100,7 +1101,7 @@ static void fimd_unbind(struct device *dev, struct device *master,
 
        fimd_atomic_disable(ctx->crtc);
 
-       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+       exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 
        if (ctx->encoder)
                exynos_dpi_remove(ctx->encoder);
index 2a3382d..fcee33a 100644 (file)
@@ -232,6 +232,7 @@ struct g2d_runqueue_node {
 
 struct g2d_data {
        struct device                   *dev;
+       void                            *dma_priv;
        struct clk                      *gate_clk;
        void __iomem                    *regs;
        int                             irq;
@@ -1409,7 +1410,7 @@ static int g2d_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       ret = exynos_drm_register_dma(drm_dev, dev);
+       ret = exynos_drm_register_dma(drm_dev, dev, &g2d->dma_priv);
        if (ret < 0) {
                dev_err(dev, "failed to enable iommu.\n");
                g2d_fini_cmdlist(g2d);
@@ -1434,7 +1435,7 @@ static void g2d_unbind(struct device *dev, struct device *master, void *data)
        priv->g2d_dev = NULL;
 
        cancel_work_sync(&g2d->runqueue_work);
-       exynos_drm_unregister_dma(g2d->drm_dev, dev);
+       exynos_drm_unregister_dma(g2d->drm_dev, dev, &g2d->dma_priv);
 }
 
 static const struct component_ops g2d_component_ops = {
index 88b6fca..45e9aee 100644 (file)
@@ -97,6 +97,7 @@ struct gsc_scaler {
 struct gsc_context {
        struct exynos_drm_ipp ipp;
        struct drm_device *drm_dev;
+       void            *dma_priv;
        struct device   *dev;
        struct exynos_drm_ipp_task      *task;
        struct exynos_drm_ipp_formats   *formats;
@@ -1169,7 +1170,7 @@ static int gsc_bind(struct device *dev, struct device *master, void *data)
 
        ctx->drm_dev = drm_dev;
        ctx->drm_dev = drm_dev;
-       exynos_drm_register_dma(drm_dev, dev);
+       exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 
        exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
                        DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -1189,7 +1190,7 @@ static void gsc_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &ctx->ipp;
 
        exynos_drm_ipp_unregister(dev, ipp);
-       exynos_drm_unregister_dma(drm_dev, dev);
+       exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static const struct component_ops gsc_component_ops = {
index b984829..dafa87b 100644 (file)
@@ -56,6 +56,7 @@ struct rot_variant {
 struct rot_context {
        struct exynos_drm_ipp ipp;
        struct drm_device *drm_dev;
+       void            *dma_priv;
        struct device   *dev;
        void __iomem    *regs;
        struct clk      *clock;
@@ -243,7 +244,7 @@ static int rotator_bind(struct device *dev, struct device *master, void *data)
 
        rot->drm_dev = drm_dev;
        ipp->drm_dev = drm_dev;
-       exynos_drm_register_dma(drm_dev, dev);
+       exynos_drm_register_dma(drm_dev, dev, &rot->dma_priv);
 
        exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
                           DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE,
@@ -261,7 +262,7 @@ static void rotator_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &rot->ipp;
 
        exynos_drm_ipp_unregister(dev, ipp);
-       exynos_drm_unregister_dma(rot->drm_dev, rot->dev);
+       exynos_drm_unregister_dma(rot->drm_dev, rot->dev, &rot->dma_priv);
 }
 
 static const struct component_ops rotator_component_ops = {
index 497973e..93c43c8 100644 (file)
@@ -39,6 +39,7 @@ struct scaler_data {
 struct scaler_context {
        struct exynos_drm_ipp           ipp;
        struct drm_device               *drm_dev;
+       void                            *dma_priv;
        struct device                   *dev;
        void __iomem                    *regs;
        struct clk                      *clock[SCALER_MAX_CLK];
@@ -450,7 +451,7 @@ static int scaler_bind(struct device *dev, struct device *master, void *data)
 
        scaler->drm_dev = drm_dev;
        ipp->drm_dev = drm_dev;
-       exynos_drm_register_dma(drm_dev, dev);
+       exynos_drm_register_dma(drm_dev, dev, &scaler->dma_priv);
 
        exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
                        DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -470,7 +471,8 @@ static void scaler_unbind(struct device *dev, struct device *master,
        struct exynos_drm_ipp *ipp = &scaler->ipp;
 
        exynos_drm_ipp_unregister(dev, ipp);
-       exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev);
+       exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev,
+                                 &scaler->dma_priv);
 }
 
 static const struct component_ops scaler_component_ops = {
index 9ff921f..f141916 100644 (file)
@@ -1805,18 +1805,10 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
 
        hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
 
-       if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) {
+       if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV)
                if (IS_ERR(hdata->reg_hdmi_en))
                        return PTR_ERR(hdata->reg_hdmi_en);
 
-               ret = regulator_enable(hdata->reg_hdmi_en);
-               if (ret) {
-                       DRM_DEV_ERROR(dev,
-                                     "failed to enable hdmi-en regulator\n");
-                       return ret;
-               }
-       }
-
        return hdmi_bridge_init(hdata);
 }
 
@@ -2023,6 +2015,15 @@ static int hdmi_probe(struct platform_device *pdev)
                }
        }
 
+       if (!IS_ERR(hdata->reg_hdmi_en)) {
+               ret = regulator_enable(hdata->reg_hdmi_en);
+               if (ret) {
+                       DRM_DEV_ERROR(dev,
+                             "failed to enable hdmi-en regulator\n");
+                       goto err_hdmiphy;
+               }
+       }
+
        pm_runtime_enable(dev);
 
        audio_infoframe = &hdata->audio.infoframe;
@@ -2047,7 +2048,8 @@ err_unregister_audio:
 
 err_rpm_disable:
        pm_runtime_disable(dev);
-
+       if (!IS_ERR(hdata->reg_hdmi_en))
+               regulator_disable(hdata->reg_hdmi_en);
 err_hdmiphy:
        if (hdata->hdmiphy_port)
                put_device(&hdata->hdmiphy_port->dev);
index 38ae9c3..21b726b 100644 (file)
@@ -94,6 +94,7 @@ struct mixer_context {
        struct platform_device *pdev;
        struct device           *dev;
        struct drm_device       *drm_dev;
+       void                    *dma_priv;
        struct exynos_drm_crtc  *crtc;
        struct exynos_drm_plane planes[MIXER_WIN_NR];
        unsigned long           flags;
@@ -894,12 +895,14 @@ static int mixer_initialize(struct mixer_context *mixer_ctx,
                }
        }
 
-       return exynos_drm_register_dma(drm_dev, mixer_ctx->dev);
+       return exynos_drm_register_dma(drm_dev, mixer_ctx->dev,
+                                      &mixer_ctx->dma_priv);
 }
 
 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 {
-       exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev);
+       exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev,
+                                 &mixer_ctx->dma_priv);
 }
 
 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
index 0da8602..e2ac098 100644 (file)
@@ -83,7 +83,6 @@
 #define VSIZE_OFST                     20
 #define LDI_INT_EN                     0x741C
 #define FRAME_END_INT_EN_OFST          1
-#define UNDERFLOW_INT_EN_OFST          2
 #define LDI_CTRL                       0x7420
 #define BPP_OFST                       3
 #define DATA_GATE_EN                   BIT(2)
index 73cd28a..8600012 100644 (file)
@@ -46,7 +46,6 @@ struct ade_hw_ctx {
        struct clk *media_noc_clk;
        struct clk *ade_pix_clk;
        struct reset_control *reset;
-       struct work_struct display_reset_wq;
        bool power_on;
        int irq;
 
@@ -136,7 +135,6 @@ static void ade_init(struct ade_hw_ctx *ctx)
         */
        ade_update_bits(base + ADE_CTRL, FRM_END_START_OFST,
                        FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND);
-       ade_update_bits(base + LDI_INT_EN, UNDERFLOW_INT_EN_OFST, MASK(1), 1);
 }
 
 static bool ade_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -304,17 +302,6 @@ static void ade_crtc_disable_vblank(struct drm_crtc *crtc)
                        MASK(1), 0);
 }
 
-static void drm_underflow_wq(struct work_struct *work)
-{
-       struct ade_hw_ctx *ctx = container_of(work, struct ade_hw_ctx,
-                                             display_reset_wq);
-       struct drm_device *drm_dev = ctx->crtc->dev;
-       struct drm_atomic_state *state;
-
-       state = drm_atomic_helper_suspend(drm_dev);
-       drm_atomic_helper_resume(drm_dev, state);
-}
-
 static irqreturn_t ade_irq_handler(int irq, void *data)
 {
        struct ade_hw_ctx *ctx = data;
@@ -331,12 +318,6 @@ static irqreturn_t ade_irq_handler(int irq, void *data)
                                MASK(1), 1);
                drm_crtc_handle_vblank(crtc);
        }
-       if (status & BIT(UNDERFLOW_INT_EN_OFST)) {
-               ade_update_bits(base + LDI_INT_CLR, UNDERFLOW_INT_EN_OFST,
-                               MASK(1), 1);
-               DRM_ERROR("LDI underflow!");
-               schedule_work(&ctx->display_reset_wq);
-       }
 
        return IRQ_HANDLED;
 }
@@ -919,7 +900,6 @@ static void *ade_hw_ctx_alloc(struct platform_device *pdev,
        if (ret)
                return ERR_PTR(-EIO);
 
-       INIT_WORK(&ctx->display_reset_wq, drm_underflow_wq);
        ctx->crtc = crtc;
 
        return ctx;
index b8c5f89..a1f2411 100644 (file)
@@ -294,7 +294,7 @@ extra-$(CONFIG_DRM_I915_WERROR) += \
                $(shell cd $(srctree)/$(src) && find * -name '*.h')))
 
 quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
-      cmd_hdrtest = $(CC) $(c_flags) -S -o /dev/null -x c /dev/null -include $<; touch $@
+      cmd_hdrtest = $(CC) $(filter-out $(CFLAGS_GCOV), $(c_flags)) -S -o /dev/null -x c /dev/null -include $<; touch $@
 
 $(obj)/%.hdrtest: $(src)/%.h FORCE
        $(call if_changed_dep,hdrtest)
index 21561ac..46c40db 100644 (file)
@@ -4466,13 +4466,19 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv)
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
 {
-       u32 val;
+       u32 mask, val;
 
-       val = MBUS_ABOX_BT_CREDIT_POOL1(16) |
-             MBUS_ABOX_BT_CREDIT_POOL2(16) |
-             MBUS_ABOX_B_CREDIT(1) |
-             MBUS_ABOX_BW_CREDIT(1);
+       mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK |
+               MBUS_ABOX_BT_CREDIT_POOL2_MASK |
+               MBUS_ABOX_B_CREDIT_MASK |
+               MBUS_ABOX_BW_CREDIT_MASK;
 
+       val = I915_READ(MBUS_ABOX_CTL);
+       val &= ~mask;
+       val |= MBUS_ABOX_BT_CREDIT_POOL1(16) |
+               MBUS_ABOX_BT_CREDIT_POOL2(16) |
+               MBUS_ABOX_B_CREDIT(1) |
+               MBUS_ABOX_BW_CREDIT(1);
        I915_WRITE(MBUS_ABOX_CTL, val);
 }
 
@@ -4968,8 +4974,21 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)
                I915_WRITE(BW_BUDDY1_CTL, BW_BUDDY_DISABLE);
                I915_WRITE(BW_BUDDY2_CTL, BW_BUDDY_DISABLE);
        } else {
+               u32 val;
+
                I915_WRITE(BW_BUDDY1_PAGE_MASK, table[i].page_mask);
                I915_WRITE(BW_BUDDY2_PAGE_MASK, table[i].page_mask);
+
+               /* Wa_22010178259:tgl */
+               val = I915_READ(BW_BUDDY1_CTL);
+               val &= ~BW_BUDDY_TLB_REQ_TIMER_MASK;
+               val |= REG_FIELD_PREP(BW_BUDDY_TLB_REQ_TIMER_MASK, 0x8);
+               I915_WRITE(BW_BUDDY1_CTL, val);
+
+               val = I915_READ(BW_BUDDY2_CTL);
+               val &= ~BW_BUDDY_TLB_REQ_TIMER_MASK;
+               val |= REG_FIELD_PREP(BW_BUDDY_TLB_REQ_TIMER_MASK, 0x8);
+               I915_WRITE(BW_BUDDY2_CTL, val);
        }
 }
 
index 89c9cf5..8302505 100644 (file)
@@ -852,10 +852,12 @@ void intel_psr_enable(struct intel_dp *intel_dp,
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
-       if (!crtc_state->has_psr)
+       if (!CAN_PSR(dev_priv) || dev_priv->psr.dp != intel_dp)
                return;
 
-       if (WARN_ON(!CAN_PSR(dev_priv)))
+       dev_priv->psr.force_mode_changed = false;
+
+       if (!crtc_state->has_psr)
                return;
 
        WARN_ON(dev_priv->drrs.dp);
@@ -1009,6 +1011,8 @@ void intel_psr_update(struct intel_dp *intel_dp,
        if (!CAN_PSR(dev_priv) || READ_ONCE(psr->dp) != intel_dp)
                return;
 
+       dev_priv->psr.force_mode_changed = false;
+
        mutex_lock(&dev_priv->psr.lock);
 
        enable = crtc_state->has_psr && psr_global_enabled(psr->debug);
@@ -1534,7 +1538,7 @@ void intel_psr_atomic_check(struct drm_connector *connector,
        struct drm_crtc_state *crtc_state;
 
        if (!CAN_PSR(dev_priv) || !new_state->crtc ||
-           dev_priv->psr.initially_probed)
+           !dev_priv->psr.force_mode_changed)
                return;
 
        intel_connector = to_intel_connector(connector);
@@ -1545,5 +1549,18 @@ void intel_psr_atomic_check(struct drm_connector *connector,
        crtc_state = drm_atomic_get_new_crtc_state(new_state->state,
                                                   new_state->crtc);
        crtc_state->mode_changed = true;
-       dev_priv->psr.initially_probed = true;
+}
+
+void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp)
+{
+       struct drm_i915_private *dev_priv;
+
+       if (!intel_dp)
+               return;
+
+       dev_priv = dp_to_i915(intel_dp);
+       if (!CAN_PSR(dev_priv) || intel_dp != dev_priv->psr.dp)
+               return;
+
+       dev_priv->psr.force_mode_changed = true;
 }
index c58a1d4..274fc6b 100644 (file)
@@ -40,5 +40,6 @@ bool intel_psr_enabled(struct intel_dp *intel_dp);
 void intel_psr_atomic_check(struct drm_connector *connector,
                            struct drm_connector_state *old_state,
                            struct drm_connector_state *new_state);
+void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp);
 
 #endif /* __INTEL_PSR_H__ */
index 60c984e..7643a30 100644 (file)
@@ -423,7 +423,8 @@ eb_validate_vma(struct i915_execbuffer *eb,
        if (unlikely(entry->flags & eb->invalid_flags))
                return -EINVAL;
 
-       if (unlikely(entry->alignment && !is_power_of_2(entry->alignment)))
+       if (unlikely(entry->alignment &&
+                    !is_power_of_2_u64(entry->alignment)))
                return -EINVAL;
 
        /*
index 3598521..5da9f9e 100644 (file)
@@ -225,6 +225,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 
                /* But keep the pointer alive for RCU-protected lookups */
                call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+               cond_resched();
        }
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
index f7e4b39..59b387a 100644 (file)
@@ -256,8 +256,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
        with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
                freed = i915_gem_shrink(i915, -1UL, NULL,
                                        I915_SHRINK_BOUND |
-                                       I915_SHRINK_UNBOUND |
-                                       I915_SHRINK_ACTIVE);
+                                       I915_SHRINK_UNBOUND);
        }
 
        return freed;
@@ -336,7 +335,6 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
        freed_pages = 0;
        with_intel_runtime_pm(&i915->runtime_pm, wakeref)
                freed_pages += i915_gem_shrink(i915, -1UL, NULL,
-                                              I915_SHRINK_ACTIVE |
                                               I915_SHRINK_BOUND |
                                               I915_SHRINK_UNBOUND |
                                               I915_SHRINK_WRITEBACK);
index ef7c74c..43912e9 100644 (file)
@@ -570,7 +570,7 @@ static bool assert_mmap_offset(struct drm_i915_private *i915,
 
        obj = i915_gem_object_create_internal(i915, size);
        if (IS_ERR(obj))
-               return PTR_ERR(obj);
+               return false;
 
        mmo = mmap_offset_attach(obj, I915_MMAP_OFFSET_GTT, NULL);
        i915_gem_object_put(obj);
index 8a5054f..24c99d0 100644 (file)
@@ -147,24 +147,32 @@ long intel_gt_retire_requests_timeout(struct intel_gt *gt, long timeout)
 
                        fence = i915_active_fence_get(&tl->last_request);
                        if (fence) {
+                               mutex_unlock(&tl->mutex);
+
                                timeout = dma_fence_wait_timeout(fence,
                                                                 interruptible,
                                                                 timeout);
                                dma_fence_put(fence);
+
+                               /* Retirement is best effort */
+                               if (!mutex_trylock(&tl->mutex)) {
+                                       active_count++;
+                                       goto out_active;
+                               }
                        }
                }
 
                if (!retire_requests(tl) || flush_submission(gt))
                        active_count++;
+               mutex_unlock(&tl->mutex);
 
-               spin_lock(&timelines->lock);
+out_active:    spin_lock(&timelines->lock);
 
-               /* Resume iteration after dropping lock */
+               /* Resume list iteration after reacquiring spinlock */
                list_safe_reset_next(tl, tn, link);
                if (atomic_dec_and_test(&tl->active_count))
                        list_del(&tl->link);
 
-               mutex_unlock(&tl->mutex);
 
                /* Defer the final release to after the spinlock */
                if (refcount_dec_and_test(&tl->kref.refcount)) {
index fe8a59a..940e7f7 100644 (file)
@@ -1679,11 +1679,9 @@ need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
        if (!intel_engine_has_timeslices(engine))
                return false;
 
-       if (list_is_last(&rq->sched.link, &engine->active.requests))
-               return false;
-
-       hint = max(rq_prio(list_next_entry(rq, sched.link)),
-                  engine->execlists.queue_priority_hint);
+       hint = engine->execlists.queue_priority_hint;
+       if (!list_is_last(&rq->sched.link, &engine->active.requests))
+               hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
 
        return hint >= effective_prio(rq);
 }
@@ -1725,6 +1723,18 @@ static void set_timeslice(struct intel_engine_cs *engine)
        set_timer_ms(&engine->execlists.timer, active_timeslice(engine));
 }
 
+static void start_timeslice(struct intel_engine_cs *engine)
+{
+       struct intel_engine_execlists *execlists = &engine->execlists;
+
+       execlists->switch_priority_hint = execlists->queue_priority_hint;
+
+       if (timer_pending(&execlists->timer))
+               return;
+
+       set_timer_ms(&execlists->timer, timeslice(engine));
+}
+
 static void record_preemption(struct intel_engine_execlists *execlists)
 {
        (void)I915_SELFTEST_ONLY(execlists->preempt_hang.count++);
@@ -1888,11 +1898,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                                 * Even if ELSP[1] is occupied and not worthy
                                 * of timeslices, our queue might be.
                                 */
-                               if (!execlists->timer.expires &&
-                                   need_timeslice(engine, last))
-                                       set_timer_ms(&execlists->timer,
-                                                    timeslice(engine));
-
+                               start_timeslice(engine);
                                return;
                        }
                }
@@ -1927,7 +1933,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                        if (last && !can_merge_rq(last, rq)) {
                                spin_unlock(&ve->base.active.lock);
-                               return; /* leave this for another */
+                               start_timeslice(engine);
+                               return; /* leave this for another sibling */
                        }
 
                        ENGINE_TRACE(engine,
index 8771652..d8d9f11 100644 (file)
@@ -192,11 +192,15 @@ static void cacheline_release(struct intel_timeline_cacheline *cl)
 
 static void cacheline_free(struct intel_timeline_cacheline *cl)
 {
+       if (!i915_active_acquire_if_busy(&cl->active)) {
+               __idle_cacheline_free(cl);
+               return;
+       }
+
        GEM_BUG_ON(ptr_test_bit(cl->vaddr, CACHELINE_FREE));
        cl->vaddr = ptr_set_bit(cl->vaddr, CACHELINE_FREE);
 
-       if (i915_active_is_idle(&cl->active))
-               __idle_cacheline_free(cl);
+       i915_active_release(&cl->active);
 }
 
 int intel_timeline_init(struct intel_timeline *timeline,
index 4e292d4..173a7f2 100644 (file)
@@ -575,24 +575,19 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
 static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
                                     struct i915_wa_list *wal)
 {
-       u32 val;
-
        /* Wa_1409142259:tgl */
        WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
                          GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
 
-       /* Wa_1604555607:tgl */
-       val = intel_uncore_read(engine->uncore, FF_MODE2);
-       val &= ~FF_MODE2_TDS_TIMER_MASK;
-       val |= FF_MODE2_TDS_TIMER_128;
        /*
-        * FIXME: FF_MODE2 register is not readable till TGL B0. We can
-        * enable verification of WA from the later steppings, which enables
-        * the read of FF_MODE2.
+        * Wa_1604555607:gen12 and Wa_1608008084:gen12
+        * FF_MODE2 register will return the wrong value when read. The default
+        * value for this register is zero for all fields and there are no bit
+        * masks. So instead of doing a RMW we should just write the TDS timer
+        * value for Wa_1604555607.
         */
-       wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK, val,
-              IS_TGL_REVID(engine->i915, TGL_REVID_A0, TGL_REVID_A0) ? 0 :
-                           FF_MODE2_TDS_TIMER_MASK);
+       wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK,
+              FF_MODE2_TDS_TIMER_128, 0);
 }
 
 static void
index e1c313d..a62bdf9 100644 (file)
@@ -457,7 +457,8 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected)
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 
        /* TODO: add more platforms support */
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+               IS_COFFEELAKE(dev_priv)) {
                if (connected) {
                        vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
                                SFUSE_STRAP_DDID_DETECTED;
index 2477a1e..ae139f0 100644 (file)
@@ -151,12 +151,12 @@ static void dmabuf_gem_object_free(struct kref *kref)
                        dmabuf_obj = container_of(pos,
                                        struct intel_vgpu_dmabuf_obj, list);
                        if (dmabuf_obj == obj) {
+                               list_del(pos);
                                intel_gvt_hypervisor_put_vfio_device(vgpu);
                                idr_remove(&vgpu->object_idr,
                                           dmabuf_obj->dmabuf_id);
                                kfree(dmabuf_obj->info);
                                kfree(dmabuf_obj);
-                               list_del(pos);
                                break;
                        }
                }
index 867e762..33569b9 100644 (file)
@@ -147,15 +147,14 @@ static void virt_vbt_generation(struct vbt *v)
        /* there's features depending on version! */
        v->header.version = 155;
        v->header.header_size = sizeof(v->header);
-       v->header.vbt_size = sizeof(struct vbt) - sizeof(v->header);
+       v->header.vbt_size = sizeof(struct vbt);
        v->header.bdb_offset = offsetof(struct vbt, bdb_header);
 
        strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK");
        v->bdb_header.version = 186; /* child_dev_size = 33 */
        v->bdb_header.header_size = sizeof(v->bdb_header);
 
-       v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header)
-               - sizeof(struct bdb_header);
+       v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header);
 
        /* general features */
        v->general_features_header.id = BDB_GENERAL_FEATURES;
index 85bd9bf..345c2aa 100644 (file)
@@ -272,10 +272,17 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
 {
        struct intel_gvt *gvt = vgpu->gvt;
 
-       mutex_lock(&vgpu->vgpu_lock);
-
        WARN(vgpu->active, "vGPU is still active!\n");
 
+       /*
+        * remove idr first so later clean can judge if need to stop
+        * service if no active vgpu.
+        */
+       mutex_lock(&gvt->lock);
+       idr_remove(&gvt->vgpu_idr, vgpu->id);
+       mutex_unlock(&gvt->lock);
+
+       mutex_lock(&vgpu->vgpu_lock);
        intel_gvt_debugfs_remove_vgpu(vgpu);
        intel_vgpu_clean_sched_policy(vgpu);
        intel_vgpu_clean_submission(vgpu);
@@ -290,7 +297,6 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
        mutex_unlock(&vgpu->vgpu_lock);
 
        mutex_lock(&gvt->lock);
-       idr_remove(&gvt->vgpu_idr, vgpu->id);
        if (idr_is_empty(&gvt->vgpu_idr))
                intel_gvt_clean_irq(gvt);
        intel_gvt_update_vgpu_types(gvt);
@@ -560,9 +566,9 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
 
                intel_vgpu_reset_mmio(vgpu, dmlr);
                populate_pvinfo_page(vgpu);
-               intel_vgpu_reset_display(vgpu);
 
                if (dmlr) {
+                       intel_vgpu_reset_display(vgpu);
                        intel_vgpu_reset_cfg_space(vgpu);
                        /* only reset the failsafe mode when dmlr reset */
                        vgpu->failsafe = false;
index f7385ab..8410330 100644 (file)
@@ -56,6 +56,7 @@
 #include "display/intel_hotplug.h"
 #include "display/intel_overlay.h"
 #include "display/intel_pipe_crc.h"
+#include "display/intel_psr.h"
 #include "display/intel_sprite.h"
 #include "display/intel_vga.h"
 
@@ -330,6 +331,8 @@ static int i915_driver_modeset_probe(struct drm_i915_private *i915)
 
        intel_init_ipc(i915);
 
+       intel_psr_set_force_mode_changed(i915->psr.dp);
+
        return 0;
 
 cleanup_gem:
index 077af22..810e3cc 100644 (file)
@@ -505,7 +505,7 @@ struct i915_psr {
        bool dc3co_enabled;
        u32 dc3co_exit_delay;
        struct delayed_work idle_work;
-       bool initially_probed;
+       bool force_mode_changed;
 };
 
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
index 83f0140..f631f6d 100644 (file)
@@ -437,7 +437,7 @@ static const struct intel_device_info snb_m_gt2_info = {
        .has_rc6 = 1, \
        .has_rc6p = 1, \
        .has_rps = true, \
-       .ppgtt_type = INTEL_PPGTT_FULL, \
+       .ppgtt_type = INTEL_PPGTT_ALIASING, \
        .ppgtt_size = 31, \
        IVB_PIPE_OFFSETS, \
        IVB_CURSOR_OFFSETS, \
@@ -494,7 +494,7 @@ static const struct intel_device_info vlv_info = {
        .has_rps = true,
        .display.has_gmch = 1,
        .display.has_hotplug = 1,
-       .ppgtt_type = INTEL_PPGTT_FULL,
+       .ppgtt_type = INTEL_PPGTT_ALIASING,
        .ppgtt_size = 31,
        .has_snoop = true,
        .has_coherent_ggtt = false,
index 0f556d8..3b6b913 100644 (file)
@@ -1954,9 +1954,10 @@ out:
        return i915_vma_get(oa_bo->vma);
 }
 
-static int emit_oa_config(struct i915_perf_stream *stream,
-                         struct i915_oa_config *oa_config,
-                         struct intel_context *ce)
+static struct i915_request *
+emit_oa_config(struct i915_perf_stream *stream,
+              struct i915_oa_config *oa_config,
+              struct intel_context *ce)
 {
        struct i915_request *rq;
        struct i915_vma *vma;
@@ -1964,7 +1965,7 @@ static int emit_oa_config(struct i915_perf_stream *stream,
 
        vma = get_oa_vma(stream, oa_config);
        if (IS_ERR(vma))
-               return PTR_ERR(vma);
+               return ERR_CAST(vma);
 
        err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
        if (err)
@@ -1989,13 +1990,17 @@ static int emit_oa_config(struct i915_perf_stream *stream,
        err = rq->engine->emit_bb_start(rq,
                                        vma->node.start, 0,
                                        I915_DISPATCH_SECURE);
+       if (err)
+               goto err_add_request;
+
+       i915_request_get(rq);
 err_add_request:
        i915_request_add(rq);
 err_vma_unpin:
        i915_vma_unpin(vma);
 err_vma_put:
        i915_vma_put(vma);
-       return err;
+       return err ? ERR_PTR(err) : rq;
 }
 
 static struct intel_context *oa_context(struct i915_perf_stream *stream)
@@ -2003,7 +2008,8 @@ static struct intel_context *oa_context(struct i915_perf_stream *stream)
        return stream->pinned_ctx ?: stream->engine->kernel_context;
 }
 
-static int hsw_enable_metric_set(struct i915_perf_stream *stream)
+static struct i915_request *
+hsw_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
 
@@ -2406,7 +2412,8 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
        return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
 }
 
-static int gen8_enable_metric_set(struct i915_perf_stream *stream)
+static struct i915_request *
+gen8_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
        struct i915_oa_config *oa_config = stream->oa_config;
@@ -2448,7 +2455,7 @@ static int gen8_enable_metric_set(struct i915_perf_stream *stream)
         */
        ret = lrc_configure_all_contexts(stream, oa_config);
        if (ret)
-               return ret;
+               return ERR_PTR(ret);
 
        return emit_oa_config(stream, oa_config, oa_context(stream));
 }
@@ -2460,7 +2467,8 @@ static u32 oag_report_ctx_switches(const struct i915_perf_stream *stream)
                             0 : GEN12_OAG_OA_DEBUG_DISABLE_CTX_SWITCH_REPORTS);
 }
 
-static int gen12_enable_metric_set(struct i915_perf_stream *stream)
+static struct i915_request *
+gen12_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
        struct i915_oa_config *oa_config = stream->oa_config;
@@ -2491,7 +2499,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         */
        ret = gen12_configure_all_contexts(stream, oa_config);
        if (ret)
-               return ret;
+               return ERR_PTR(ret);
 
        /*
         * For Gen12, performance counters are context
@@ -2501,7 +2509,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
        if (stream->ctx) {
                ret = gen12_configure_oar_context(stream, true);
                if (ret)
-                       return ret;
+                       return ERR_PTR(ret);
        }
 
        return emit_oa_config(stream, oa_config, oa_context(stream));
@@ -2696,6 +2704,20 @@ static const struct i915_perf_stream_ops i915_oa_stream_ops = {
        .read = i915_oa_read,
 };
 
+static int i915_perf_stream_enable_sync(struct i915_perf_stream *stream)
+{
+       struct i915_request *rq;
+
+       rq = stream->perf->ops.enable_metric_set(stream);
+       if (IS_ERR(rq))
+               return PTR_ERR(rq);
+
+       i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT);
+       i915_request_put(rq);
+
+       return 0;
+}
+
 /**
  * i915_oa_stream_init - validate combined props for OA stream and init
  * @stream: An i915 perf stream
@@ -2829,7 +2851,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
        stream->ops = &i915_oa_stream_ops;
        perf->exclusive_stream = stream;
 
-       ret = perf->ops.enable_metric_set(stream);
+       ret = i915_perf_stream_enable_sync(stream);
        if (ret) {
                DRM_DEBUG("Unable to enable metric set\n");
                goto err_enable;
@@ -3147,7 +3169,7 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream,
                return -EINVAL;
 
        if (config != stream->oa_config) {
-               int err;
+               struct i915_request *rq;
 
                /*
                 * If OA is bound to a specific context, emit the
@@ -3158,11 +3180,13 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream,
                 * When set globally, we use a low priority kernel context,
                 * so it will effectively take effect when idle.
                 */
-               err = emit_oa_config(stream, config, oa_context(stream));
-               if (err == 0)
+               rq = emit_oa_config(stream, config, oa_context(stream));
+               if (!IS_ERR(rq)) {
                        config = xchg(&stream->oa_config, config);
-               else
-                       ret = err;
+                       i915_request_put(rq);
+               } else {
+                       ret = PTR_ERR(rq);
+               }
        }
 
        i915_oa_config_put(config);
index 45e5814..a0e22f0 100644 (file)
@@ -339,7 +339,8 @@ struct i915_oa_ops {
         * counter reports being sampled. May apply system constraints such as
         * disabling EU clock gating as required.
         */
-       int (*enable_metric_set)(struct i915_perf_stream *stream);
+       struct i915_request *
+               (*enable_metric_set)(struct i915_perf_stream *stream);
 
        /**
         * @disable_metric_set: Remove system constraints associated with using
index ec02994..aa729d0 100644 (file)
@@ -822,11 +822,6 @@ static ssize_t i915_pmu_event_show(struct device *dev,
        return sprintf(buf, "config=0x%lx\n", eattr->val);
 }
 
-static struct attribute_group i915_pmu_events_attr_group = {
-       .name = "events",
-       /* Patch in attrs at runtime. */
-};
-
 static ssize_t
 i915_pmu_get_attr_cpumask(struct device *dev,
                          struct device_attribute *attr,
@@ -846,13 +841,6 @@ static const struct attribute_group i915_pmu_cpumask_attr_group = {
        .attrs = i915_cpumask_attrs,
 };
 
-static const struct attribute_group *i915_pmu_attr_groups[] = {
-       &i915_pmu_format_attr_group,
-       &i915_pmu_events_attr_group,
-       &i915_pmu_cpumask_attr_group,
-       NULL
-};
-
 #define __event(__config, __name, __unit) \
 { \
        .config = (__config), \
@@ -1026,23 +1014,23 @@ err_alloc:
 
 static void free_event_attributes(struct i915_pmu *pmu)
 {
-       struct attribute **attr_iter = i915_pmu_events_attr_group.attrs;
+       struct attribute **attr_iter = pmu->events_attr_group.attrs;
 
        for (; *attr_iter; attr_iter++)
                kfree((*attr_iter)->name);
 
-       kfree(i915_pmu_events_attr_group.attrs);
+       kfree(pmu->events_attr_group.attrs);
        kfree(pmu->i915_attr);
        kfree(pmu->pmu_attr);
 
-       i915_pmu_events_attr_group.attrs = NULL;
+       pmu->events_attr_group.attrs = NULL;
        pmu->i915_attr = NULL;
        pmu->pmu_attr = NULL;
 }
 
 static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 {
-       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
+       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
 
        GEM_BUG_ON(!pmu->base.event_init);
 
@@ -1055,7 +1043,7 @@ static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 
 static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
 {
-       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node);
+       struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
        unsigned int target;
 
        GEM_BUG_ON(!pmu->base.event_init);
@@ -1072,8 +1060,6 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
        return 0;
 }
 
-static enum cpuhp_state cpuhp_slot = CPUHP_INVALID;
-
 static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
 {
        enum cpuhp_state slot;
@@ -1087,21 +1073,22 @@ static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
                return ret;
 
        slot = ret;
-       ret = cpuhp_state_add_instance(slot, &pmu->node);
+       ret = cpuhp_state_add_instance(slot, &pmu->cpuhp.node);
        if (ret) {
                cpuhp_remove_multi_state(slot);
                return ret;
        }
 
-       cpuhp_slot = slot;
+       pmu->cpuhp.slot = slot;
        return 0;
 }
 
 static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
 {
-       WARN_ON(cpuhp_slot == CPUHP_INVALID);
-       WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &pmu->node));
-       cpuhp_remove_multi_state(cpuhp_slot);
+       WARN_ON(pmu->cpuhp.slot == CPUHP_INVALID);
+       WARN_ON(cpuhp_state_remove_instance(pmu->cpuhp.slot, &pmu->cpuhp.node));
+       cpuhp_remove_multi_state(pmu->cpuhp.slot);
+       pmu->cpuhp.slot = CPUHP_INVALID;
 }
 
 static bool is_igp(struct drm_i915_private *i915)
@@ -1118,6 +1105,13 @@ static bool is_igp(struct drm_i915_private *i915)
 void i915_pmu_register(struct drm_i915_private *i915)
 {
        struct i915_pmu *pmu = &i915->pmu;
+       const struct attribute_group *attr_groups[] = {
+               &i915_pmu_format_attr_group,
+               &pmu->events_attr_group,
+               &i915_pmu_cpumask_attr_group,
+               NULL
+       };
+
        int ret = -ENOMEM;
 
        if (INTEL_GEN(i915) <= 2) {
@@ -1128,6 +1122,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
        spin_lock_init(&pmu->lock);
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
+       pmu->cpuhp.slot = CPUHP_INVALID;
 
        if (!is_igp(i915)) {
                pmu->name = kasprintf(GFP_KERNEL,
@@ -1143,11 +1138,16 @@ void i915_pmu_register(struct drm_i915_private *i915)
        if (!pmu->name)
                goto err;
 
-       i915_pmu_events_attr_group.attrs = create_event_attributes(pmu);
-       if (!i915_pmu_events_attr_group.attrs)
+       pmu->events_attr_group.name = "events";
+       pmu->events_attr_group.attrs = create_event_attributes(pmu);
+       if (!pmu->events_attr_group.attrs)
                goto err_name;
 
-       pmu->base.attr_groups   = i915_pmu_attr_groups;
+       pmu->base.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
+                                       GFP_KERNEL);
+       if (!pmu->base.attr_groups)
+               goto err_attr;
+
        pmu->base.task_ctx_nr   = perf_invalid_context;
        pmu->base.event_init    = i915_pmu_event_init;
        pmu->base.add           = i915_pmu_event_add;
@@ -1159,7 +1159,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
        ret = perf_pmu_register(&pmu->base, pmu->name, -1);
        if (ret)
-               goto err_attr;
+               goto err_groups;
 
        ret = i915_pmu_register_cpuhp_state(pmu);
        if (ret)
@@ -1169,6 +1169,8 @@ void i915_pmu_register(struct drm_i915_private *i915)
 
 err_unreg:
        perf_pmu_unregister(&pmu->base);
+err_groups:
+       kfree(pmu->base.attr_groups);
 err_attr:
        pmu->base.event_init = NULL;
        free_event_attributes(pmu);
@@ -1194,6 +1196,7 @@ void i915_pmu_unregister(struct drm_i915_private *i915)
 
        perf_pmu_unregister(&pmu->base);
        pmu->base.event_init = NULL;
+       kfree(pmu->base.attr_groups);
        if (!is_igp(i915))
                kfree(pmu->name);
        free_event_attributes(pmu);
index 6c1647c..f1d6cad 100644 (file)
@@ -39,9 +39,12 @@ struct i915_pmu_sample {
 
 struct i915_pmu {
        /**
-        * @node: List node for CPU hotplug handling.
+        * @cpuhp: Struct used for CPU hotplug handling.
         */
-       struct hlist_node node;
+       struct {
+               struct hlist_node node;
+               enum cpuhp_state slot;
+       } cpuhp;
        /**
         * @base: PMU base.
         */
@@ -105,6 +108,10 @@ struct i915_pmu {
         */
        ktime_t sleep_last;
        /**
+        * @events_attr_group: Device events attribute group.
+        */
+       struct attribute_group events_attr_group;
+       /**
         * @i915_attr: Memory block holding device attributes.
         */
        void *i915_attr;
index 6cc55c1..3575fd3 100644 (file)
@@ -7757,6 +7757,7 @@ enum {
 #define BW_BUDDY1_CTL                  _MMIO(0x45140)
 #define BW_BUDDY2_CTL                  _MMIO(0x45150)
 #define   BW_BUDDY_DISABLE             REG_BIT(31)
+#define   BW_BUDDY_TLB_REQ_TIMER_MASK  REG_GENMASK(21, 16)
 
 #define BW_BUDDY1_PAGE_MASK            _MMIO(0x45144)
 #define BW_BUDDY2_PAGE_MASK            _MMIO(0x45154)
index f56b046..a18b2a2 100644 (file)
@@ -275,7 +275,7 @@ bool i915_request_retire(struct i915_request *rq)
        spin_unlock_irq(&rq->lock);
 
        remove_from_client(rq);
-       list_del(&rq->link);
+       list_del_rcu(&rq->link);
 
        intel_context_exit(rq->context);
        intel_context_unpin(rq->context);
@@ -527,19 +527,31 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
        return NOTIFY_DONE;
 }
 
+static void irq_semaphore_cb(struct irq_work *wrk)
+{
+       struct i915_request *rq =
+               container_of(wrk, typeof(*rq), semaphore_work);
+
+       i915_schedule_bump_priority(rq, I915_PRIORITY_NOSEMAPHORE);
+       i915_request_put(rq);
+}
+
 static int __i915_sw_fence_call
 semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
 {
-       struct i915_request *request =
-               container_of(fence, typeof(*request), semaphore);
+       struct i915_request *rq = container_of(fence, typeof(*rq), semaphore);
 
        switch (state) {
        case FENCE_COMPLETE:
-               i915_schedule_bump_priority(request, I915_PRIORITY_NOSEMAPHORE);
+               if (!(READ_ONCE(rq->sched.attr.priority) & I915_PRIORITY_NOSEMAPHORE)) {
+                       i915_request_get(rq);
+                       init_irq_work(&rq->semaphore_work, irq_semaphore_cb);
+                       irq_work_queue(&rq->semaphore_work);
+               }
                break;
 
        case FENCE_FREE:
-               i915_request_put(request);
+               i915_request_put(rq);
                break;
        }
 
@@ -721,6 +733,8 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
        rq->infix = rq->ring->emit; /* end of header; start of user payload */
 
        intel_context_mark_active(ce);
+       list_add_tail_rcu(&rq->link, &tl->requests);
+
        return rq;
 
 err_unwind:
@@ -774,16 +788,26 @@ i915_request_await_start(struct i915_request *rq, struct i915_request *signal)
        struct dma_fence *fence;
        int err;
 
-       GEM_BUG_ON(i915_request_timeline(rq) ==
-                  rcu_access_pointer(signal->timeline));
+       if (i915_request_timeline(rq) == rcu_access_pointer(signal->timeline))
+               return 0;
+
+       if (i915_request_started(signal))
+               return 0;
 
        fence = NULL;
        rcu_read_lock();
        spin_lock_irq(&signal->lock);
-       if (!i915_request_started(signal) &&
-           !list_is_first(&signal->link,
-                          &rcu_dereference(signal->timeline)->requests)) {
-               struct i915_request *prev = list_prev_entry(signal, link);
+       do {
+               struct list_head *pos = READ_ONCE(signal->link.prev);
+               struct i915_request *prev;
+
+               /* Confirm signal has not been retired, the link is valid */
+               if (unlikely(i915_request_started(signal)))
+                       break;
+
+               /* Is signal the earliest request on its timeline? */
+               if (pos == &rcu_dereference(signal->timeline)->requests)
+                       break;
 
                /*
                 * Peek at the request before us in the timeline. That
@@ -791,20 +815,25 @@ i915_request_await_start(struct i915_request *rq, struct i915_request *signal)
                 * after acquiring a reference to it, confirm that it is
                 * still part of the signaler's timeline.
                 */
-               if (i915_request_get_rcu(prev)) {
-                       if (list_next_entry(prev, link) == signal)
-                               fence = &prev->fence;
-                       else
-                               i915_request_put(prev);
+               prev = list_entry(pos, typeof(*prev), link);
+               if (!i915_request_get_rcu(prev))
+                       break;
+
+               /* After the strong barrier, confirm prev is still attached */
+               if (unlikely(READ_ONCE(prev->link.next) != &signal->link)) {
+                       i915_request_put(prev);
+                       break;
                }
-       }
+
+               fence = &prev->fence;
+       } while (0);
        spin_unlock_irq(&signal->lock);
        rcu_read_unlock();
        if (!fence)
                return 0;
 
        err = 0;
-       if (intel_timeline_sync_is_later(i915_request_timeline(rq), fence))
+       if (!intel_timeline_sync_is_later(i915_request_timeline(rq), fence))
                err = i915_sw_fence_await_dma_fence(&rq->submit,
                                                    fence, 0,
                                                    I915_FENCE_GFP);
@@ -1242,8 +1271,6 @@ __i915_request_add_to_timeline(struct i915_request *rq)
                                                         0);
        }
 
-       list_add_tail(&rq->link, &timeline->requests);
-
        /*
         * Make sure that no request gazumped us - if it was allocated after
         * our i915_request_alloc() and called __i915_request_add() before
@@ -1303,9 +1330,9 @@ void __i915_request_queue(struct i915_request *rq,
         * decide whether to preempt the entire chain so that it is ready to
         * run at the earliest possible convenience.
         */
-       i915_sw_fence_commit(&rq->semaphore);
        if (attr && rq->engine->schedule)
                rq->engine->schedule(rq, attr);
+       i915_sw_fence_commit(&rq->semaphore);
        i915_sw_fence_commit(&rq->submit);
 }
 
index f57eadc..fccc339 100644 (file)
@@ -26,6 +26,7 @@
 #define I915_REQUEST_H
 
 #include <linux/dma-fence.h>
+#include <linux/irq_work.h>
 #include <linux/lockdep.h>
 
 #include "gem/i915_gem_context_types.h"
@@ -208,6 +209,7 @@ struct i915_request {
        };
        struct list_head execute_cb;
        struct i915_sw_fence semaphore;
+       struct irq_work semaphore_work;
 
        /*
         * A list of everyone we wait upon, and everyone who waits upon us.
index b0ade76..d34141f 100644 (file)
@@ -234,6 +234,11 @@ static inline u64 ptr_to_u64(const void *ptr)
        __idx;                                                          \
 })
 
+static inline bool is_power_of_2_u64(u64 n)
+{
+       return (n != 0 && ((n & (n - 1)) == 0));
+}
+
 static inline void __list_del_many(struct list_head *head,
                                   struct list_head *first)
 {
index 0dfcd17..fe85e48 100644 (file)
@@ -486,6 +486,7 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
        }
 #if IS_REACHABLE(CONFIG_MTK_CMDQ)
        if (mtk_crtc->cmdq_client) {
+               mbox_flush(mtk_crtc->cmdq_client->chan, 2000);
                cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
                cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
                cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event);
@@ -636,10 +637,18 @@ static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
 
 static int mtk_drm_crtc_init(struct drm_device *drm,
                             struct mtk_drm_crtc *mtk_crtc,
-                            struct drm_plane *primary,
-                            struct drm_plane *cursor, unsigned int pipe)
+                            unsigned int pipe)
 {
-       int ret;
+       struct drm_plane *primary = NULL;
+       struct drm_plane *cursor = NULL;
+       int i, ret;
+
+       for (i = 0; i < mtk_crtc->layer_nr; i++) {
+               if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_PRIMARY)
+                       primary = &mtk_crtc->planes[i];
+               else if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_CURSOR)
+                       cursor = &mtk_crtc->planes[i];
+       }
 
        ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor,
                                        &mtk_crtc_funcs, NULL);
@@ -689,11 +698,12 @@ static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc,
 }
 
 static inline
-enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx)
+enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx,
+                                           unsigned int num_planes)
 {
        if (plane_idx == 0)
                return DRM_PLANE_TYPE_PRIMARY;
-       else if (plane_idx == 1)
+       else if (plane_idx == (num_planes - 1))
                return DRM_PLANE_TYPE_CURSOR;
        else
                return DRM_PLANE_TYPE_OVERLAY;
@@ -712,7 +722,8 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
                ret = mtk_plane_init(drm_dev,
                                &mtk_crtc->planes[mtk_crtc->layer_nr],
                                BIT(pipe),
-                               mtk_drm_crtc_plane_type(mtk_crtc->layer_nr),
+                               mtk_drm_crtc_plane_type(mtk_crtc->layer_nr,
+                                                       num_planes),
                                mtk_ddp_comp_supported_rotations(comp));
                if (ret)
                        return ret;
@@ -807,9 +818,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
                        return ret;
        }
 
-       ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0],
-                               mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] :
-                               NULL, pipe);
+       ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe);
        if (ret < 0)
                return ret;
 
@@ -828,7 +837,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
                        drm_crtc_index(&mtk_crtc->base));
                mtk_crtc->cmdq_client = NULL;
        }
-       ret = of_property_read_u32_index(dev->of_node, "mediatek,gce-events",
+       ret = of_property_read_u32_index(priv->mutex_node,
+                                        "mediatek,gce-events",
                                         drm_crtc_index(&mtk_crtc->base),
                                         &mtk_crtc->cmdq_event);
        if (ret)
index 1f5a112..57c88de 100644 (file)
@@ -471,6 +471,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
        /* Only DMA capable components need the LARB property */
        comp->larb_dev = NULL;
        if (type != MTK_DISP_OVL &&
+           type != MTK_DISP_OVL_2L &&
            type != MTK_DISP_RDMA &&
            type != MTK_DISP_WDMA)
                return 0;
index 914cc76..c2bd683 100644 (file)
@@ -80,6 +80,7 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
                                        struct drm_plane_state *state)
 {
        struct drm_crtc_state *crtc_state;
+       int ret;
 
        if (plane != state->crtc->cursor)
                return -EINVAL;
@@ -90,6 +91,11 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
        if (!plane->state->fb)
                return -EINVAL;
 
+       ret = mtk_drm_crtc_plane_check(state->crtc, plane,
+                                      to_mtk_plane_state(state));
+       if (ret)
+               return ret;
+
        if (state->state)
                crtc_state = drm_atomic_get_existing_crtc_state(state->state,
                                                                state->crtc);
@@ -115,6 +121,7 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
        plane->state->src_y = new_state->src_y;
        plane->state->src_h = new_state->src_h;
        plane->state->src_w = new_state->src_w;
+       swap(plane->state->fb, new_state->fb);
        state->pending.async_dirty = true;
 
        mtk_drm_crtc_async_update(new_state->crtc, plane, new_state);
index 3107b07..5d75f8c 100644 (file)
@@ -601,33 +601,27 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data)
                source_id = (fault_status >> 16);
 
                /* Page fault only */
-               if ((status & mask) == BIT(i)) {
-                       WARN_ON(exception_type < 0xC1 || exception_type > 0xC4);
-
+               ret = -1;
+               if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
                        ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
-                       if (!ret) {
-                               mmu_write(pfdev, MMU_INT_CLEAR, BIT(i));
-                               status &= ~mask;
-                               continue;
-                       }
-               }
 
-               /* terminal fault, print info about the fault */
-               dev_err(pfdev->dev,
-                       "Unhandled Page fault in AS%d at VA 0x%016llX\n"
-                       "Reason: %s\n"
-                       "raw fault status: 0x%X\n"
-                       "decoded fault status: %s\n"
-                       "exception type 0x%X: %s\n"
-                       "access type 0x%X: %s\n"
-                       "source id 0x%X\n",
-                       i, addr,
-                       "TODO",
-                       fault_status,
-                       (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
-                       exception_type, panfrost_exception_name(pfdev, exception_type),
-                       access_type, access_type_name(pfdev, fault_status),
-                       source_id);
+               if (ret)
+                       /* terminal fault, print info about the fault */
+                       dev_err(pfdev->dev,
+                               "Unhandled Page fault in AS%d at VA 0x%016llX\n"
+                               "Reason: %s\n"
+                               "raw fault status: 0x%X\n"
+                               "decoded fault status: %s\n"
+                               "exception type 0x%X: %s\n"
+                               "access type 0x%X: %s\n"
+                               "source id 0x%X\n",
+                               i, addr,
+                               "TODO",
+                               fault_status,
+                               (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
+                               exception_type, panfrost_exception_name(pfdev, exception_type),
+                               access_type, access_type_name(pfdev, fault_status),
+                               source_id);
 
                mmu_write(pfdev, MMU_INT_CLEAR, mask);
 
index fd74e26..8696af1 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/mmu_notifier.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
@@ -325,6 +326,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
                            const struct pci_device_id *ent)
 {
        unsigned long flags = 0;
+       struct drm_device *dev;
        int ret;
 
        if (!ent)
@@ -365,7 +367,44 @@ static int radeon_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
-       return drm_get_pci_dev(pdev, ent, &kms_driver);
+       dev = drm_dev_alloc(&kms_driver, &pdev->dev);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto err_free;
+
+       dev->pdev = pdev;
+#ifdef __alpha__
+       dev->hose = pdev->sysdata;
+#endif
+
+       pci_set_drvdata(pdev, dev);
+
+       if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
+               dev->agp = drm_agp_init(dev);
+       if (dev->agp) {
+               dev->agp->agp_mtrr = arch_phys_wc_add(
+                       dev->agp->agp_info.aper_base,
+                       dev->agp->agp_info.aper_size *
+                       1024 * 1024);
+       }
+
+       ret = drm_dev_register(dev, ent->driver_data);
+       if (ret)
+               goto err_agp;
+
+       return 0;
+
+err_agp:
+       if (dev->agp)
+               arch_phys_wc_del(dev->agp->agp_mtrr);
+       kfree(dev->agp);
+       pci_disable_device(pdev);
+err_free:
+       drm_dev_put(dev);
+       return ret;
 }
 
 static void
@@ -575,7 +614,7 @@ radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
 
 static struct drm_driver kms_driver = {
        .driver_features =
-           DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER,
+           DRIVER_GEM | DRIVER_RENDER,
        .load = radeon_driver_load_kms,
        .open = radeon_driver_open_kms,
        .postclose = radeon_driver_postclose_kms,
index d24f23a..dd2f19b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/uaccess.h>
 #include <linux/vga_switcheroo.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
@@ -77,6 +78,11 @@ void radeon_driver_unload_kms(struct drm_device *dev)
        radeon_modeset_fini(rdev);
        radeon_device_fini(rdev);
 
+       if (dev->agp)
+               arch_phys_wc_del(dev->agp->agp_mtrr);
+       kfree(dev->agp);
+       dev->agp = NULL;
+
 done_free:
        kfree(rdev);
        dev->dev_private = NULL;
index 7c24f8f..4a64f7a 100644 (file)
@@ -107,48 +107,128 @@ static const struct de2_fmt_info de2_formats[] = {
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_XRGB4444,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_ABGR4444,
                .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_XBGR4444,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_RGBA4444,
                .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_RGBX4444,
+               .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_BGRA4444,
                .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_BGRX4444,
+               .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_ARGB1555,
                .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_XRGB1555,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_ABGR1555,
                .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_XBGR1555,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_RGBA5551,
                .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_RGBX5551,
+               .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_BGRA5551,
                .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
                .rgb = true,
                .csc = SUN8I_CSC_MODE_OFF,
        },
        {
+               /* for DE2 VI layer which ignores alpha */
+               .drm_fmt = DRM_FORMAT_BGRX5551,
+               .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
+               .drm_fmt = DRM_FORMAT_ARGB2101010,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
+               .drm_fmt = DRM_FORMAT_ABGR2101010,
+               .de2_fmt = SUN8I_MIXER_FBFMT_ABGR2101010,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
+               .drm_fmt = DRM_FORMAT_RGBA1010102,
+               .de2_fmt = SUN8I_MIXER_FBFMT_RGBA1010102,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
+               .drm_fmt = DRM_FORMAT_BGRA1010102,
+               .de2_fmt = SUN8I_MIXER_FBFMT_BGRA1010102,
+               .rgb = true,
+               .csc = SUN8I_CSC_MODE_OFF,
+       },
+       {
                .drm_fmt = DRM_FORMAT_UYVY,
                .de2_fmt = SUN8I_MIXER_FBFMT_UYVY,
                .rgb = false,
@@ -197,12 +277,6 @@ static const struct de2_fmt_info de2_formats[] = {
                .csc = SUN8I_CSC_MODE_YUV2RGB,
        },
        {
-               .drm_fmt = DRM_FORMAT_YUV444,
-               .de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-               .rgb = true,
-               .csc = SUN8I_CSC_MODE_YUV2RGB,
-       },
-       {
                .drm_fmt = DRM_FORMAT_YUV422,
                .de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
                .rgb = false,
@@ -221,12 +295,6 @@ static const struct de2_fmt_info de2_formats[] = {
                .csc = SUN8I_CSC_MODE_YUV2RGB,
        },
        {
-               .drm_fmt = DRM_FORMAT_YVU444,
-               .de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-               .rgb = true,
-               .csc = SUN8I_CSC_MODE_YVU2RGB,
-       },
-       {
                .drm_fmt = DRM_FORMAT_YVU422,
                .de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
                .rgb = false,
@@ -244,6 +312,18 @@ static const struct de2_fmt_info de2_formats[] = {
                .rgb = false,
                .csc = SUN8I_CSC_MODE_YVU2RGB,
        },
+       {
+               .drm_fmt = DRM_FORMAT_P010,
+               .de2_fmt = SUN8I_MIXER_FBFMT_P010_YUV,
+               .rgb = false,
+               .csc = SUN8I_CSC_MODE_YUV2RGB,
+       },
+       {
+               .drm_fmt = DRM_FORMAT_P210,
+               .de2_fmt = SUN8I_MIXER_FBFMT_P210_YUV,
+               .rgb = false,
+               .csc = SUN8I_CSC_MODE_YUV2RGB,
+       },
 };
 
 const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
index c6cc940..345b28b 100644 (file)
 #define SUN8I_MIXER_FBFMT_ABGR1555     17
 #define SUN8I_MIXER_FBFMT_RGBA5551     18
 #define SUN8I_MIXER_FBFMT_BGRA5551     19
+#define SUN8I_MIXER_FBFMT_ARGB2101010  20
+#define SUN8I_MIXER_FBFMT_ABGR2101010  21
+#define SUN8I_MIXER_FBFMT_RGBA1010102  22
+#define SUN8I_MIXER_FBFMT_BGRA1010102  23
 
 #define SUN8I_MIXER_FBFMT_YUYV         0
 #define SUN8I_MIXER_FBFMT_UYVY         1
 /* format 12 is semi-planar YUV411 UVUV */
 /* format 13 is semi-planar YUV411 VUVU */
 #define SUN8I_MIXER_FBFMT_YUV411       14
+/* format 15 doesn't exist */
+/* format 16 is P010 YVU */
+#define SUN8I_MIXER_FBFMT_P010_YUV     17
+/* format 18 is P210 YVU */
+#define SUN8I_MIXER_FBFMT_P210_YUV     19
+/* format 20 is packed YVU444 10-bit */
+/* format 21 is packed YUV444 10-bit */
 
 /*
  * Sub-engines listed bellow are unused for now. The EN registers are here only
index 42d445d..b8398ca 100644 (file)
@@ -398,24 +398,66 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = {
 };
 
 /*
- * While all RGB formats are supported, VI planes don't support
- * alpha blending, so there is no point having formats with alpha
- * channel if their opaque analog exist.
+ * While DE2 VI layer supports same RGB formats as UI layer, alpha
+ * channel is ignored. This structure lists all unique variants
+ * where alpha channel is replaced with "don't care" (X) channel.
  */
 static const u32 sun8i_vi_layer_formats[] = {
+       DRM_FORMAT_BGR565,
+       DRM_FORMAT_BGR888,
+       DRM_FORMAT_BGRX4444,
+       DRM_FORMAT_BGRX5551,
+       DRM_FORMAT_BGRX8888,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_RGB888,
+       DRM_FORMAT_RGBX4444,
+       DRM_FORMAT_RGBX5551,
+       DRM_FORMAT_RGBX8888,
+       DRM_FORMAT_XBGR1555,
+       DRM_FORMAT_XBGR4444,
+       DRM_FORMAT_XBGR8888,
+       DRM_FORMAT_XRGB1555,
+       DRM_FORMAT_XRGB4444,
+       DRM_FORMAT_XRGB8888,
+
+       DRM_FORMAT_NV16,
+       DRM_FORMAT_NV12,
+       DRM_FORMAT_NV21,
+       DRM_FORMAT_NV61,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
+       DRM_FORMAT_YUYV,
+       DRM_FORMAT_YVYU,
+       DRM_FORMAT_YUV411,
+       DRM_FORMAT_YUV420,
+       DRM_FORMAT_YUV422,
+       DRM_FORMAT_YVU411,
+       DRM_FORMAT_YVU420,
+       DRM_FORMAT_YVU422,
+};
+
+static const u32 sun8i_vi_layer_de3_formats[] = {
        DRM_FORMAT_ABGR1555,
+       DRM_FORMAT_ABGR2101010,
        DRM_FORMAT_ABGR4444,
+       DRM_FORMAT_ABGR8888,
        DRM_FORMAT_ARGB1555,
+       DRM_FORMAT_ARGB2101010,
        DRM_FORMAT_ARGB4444,
+       DRM_FORMAT_ARGB8888,
        DRM_FORMAT_BGR565,
        DRM_FORMAT_BGR888,
+       DRM_FORMAT_BGRA1010102,
        DRM_FORMAT_BGRA5551,
        DRM_FORMAT_BGRA4444,
+       DRM_FORMAT_BGRA8888,
        DRM_FORMAT_BGRX8888,
        DRM_FORMAT_RGB565,
        DRM_FORMAT_RGB888,
+       DRM_FORMAT_RGBA1010102,
        DRM_FORMAT_RGBA4444,
        DRM_FORMAT_RGBA5551,
+       DRM_FORMAT_RGBA8888,
        DRM_FORMAT_RGBX8888,
        DRM_FORMAT_XBGR8888,
        DRM_FORMAT_XRGB8888,
@@ -424,6 +466,8 @@ static const u32 sun8i_vi_layer_formats[] = {
        DRM_FORMAT_NV12,
        DRM_FORMAT_NV21,
        DRM_FORMAT_NV61,
+       DRM_FORMAT_P010,
+       DRM_FORMAT_P210,
        DRM_FORMAT_UYVY,
        DRM_FORMAT_VYUY,
        DRM_FORMAT_YUYV,
@@ -431,11 +475,9 @@ static const u32 sun8i_vi_layer_formats[] = {
        DRM_FORMAT_YUV411,
        DRM_FORMAT_YUV420,
        DRM_FORMAT_YUV422,
-       DRM_FORMAT_YUV444,
        DRM_FORMAT_YVU411,
        DRM_FORMAT_YVU420,
        DRM_FORMAT_YVU422,
-       DRM_FORMAT_YVU444,
 };
 
 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
@@ -443,19 +485,27 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
                                               int index)
 {
        u32 supported_encodings, supported_ranges;
+       unsigned int plane_cnt, format_count;
        struct sun8i_vi_layer *layer;
-       unsigned int plane_cnt;
+       const u32 *formats;
        int ret;
 
        layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
        if (!layer)
                return ERR_PTR(-ENOMEM);
 
+       if (mixer->cfg->is_de3) {
+               formats = sun8i_vi_layer_de3_formats;
+               format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
+       } else {
+               formats = sun8i_vi_layer_formats;
+               format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
+       }
+
        /* possible crtcs are set later */
        ret = drm_universal_plane_init(drm, &layer->plane, 0,
                                       &sun8i_vi_layer_funcs,
-                                      sun8i_vi_layer_formats,
-                                      ARRAY_SIZE(sun8i_vi_layer_formats),
+                                      formats, format_count,
                                       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
        if (ret) {
                dev_err(drm->dev, "Couldn't initialize layer\n");
index 49ed557..953c82a 100644 (file)
@@ -515,6 +515,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
                fbo->base.base.resv = &fbo->base.base._resv;
 
        dma_resv_init(&fbo->base.base._resv);
+       fbo->base.base.dev = NULL;
        ret = dma_resv_trylock(&fbo->base.base._resv);
        WARN_ON(!ret);
 
index 017a9e0..3af7ec8 100644 (file)
@@ -42,8 +42,8 @@ static int virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev,
                 * "f91a9dd35715 Fix unlinking resources from hash
                 * table." (Feb 2019) fixes the bug.
                 */
-               static int handle;
-               handle++;
+               static atomic_t seqno = ATOMIC_INIT(0);
+               int handle = atomic_inc_return(&seqno);
                *resid = handle + 1;
        } else {
                int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
@@ -99,6 +99,7 @@ struct drm_gem_object *virtio_gpu_create_object(struct drm_device *dev,
                return NULL;
 
        bo->base.base.funcs = &virtio_gpu_gem_funcs;
+       bo->base.map_cached = true;
        return &bo->base.base;
 }
 
index ae79a7c..fa70415 100644 (file)
@@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (data->has_sp) {
                input2 = input_allocate_device();
                if (!input2) {
-                       input_free_device(input2);
+                       ret = -ENOMEM;
                        goto exit;
                }
 
index 6ac8bec..d732d1d 100644 (file)
@@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                unsigned long **bit, int *max)
 {
        if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
-                       usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
+                       usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
+                       usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
                /* The fn key on Apple USB keyboards */
                set_bit(EV_REP, hi->input->evbit);
                hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
index 3f6abd1..db6da21 100644 (file)
@@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
 struct bigben_device {
        struct hid_device *hid;
        struct hid_report *report;
+       bool removed;
        u8 led_state;         /* LED1 = 1 .. LED4 = 8 */
        u8 right_motor_on;    /* right motor off/on 0/1 */
        u8 left_motor_force;  /* left motor force 0-255 */
@@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
                struct bigben_device, worker);
        struct hid_field *report_field = bigben->report->field[0];
 
+       if (bigben->removed)
+               return;
+
        if (bigben->work_led) {
                bigben->work_led = false;
                report_field->value[0] = 0x01; /* 1 = led message */
@@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
 static int hid_bigben_play_effect(struct input_dev *dev, void *data,
                         struct ff_effect *effect)
 {
-       struct bigben_device *bigben = data;
+       struct hid_device *hid = input_get_drvdata(dev);
+       struct bigben_device *bigben = hid_get_drvdata(hid);
        u8 right_motor_on;
        u8 left_motor_force;
 
+       if (!bigben) {
+               hid_err(hid, "no device data\n");
+               return 0;
+       }
+
        if (effect->type != FF_RUMBLE)
                return 0;
 
@@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
 {
        struct bigben_device *bigben = hid_get_drvdata(hid);
 
+       bigben->removed = true;
        cancel_work_sync(&bigben->worker);
-       hid_hw_close(hid);
        hid_hw_stop(hid);
 }
 
@@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
                return -ENOMEM;
        hid_set_drvdata(hid, bigben);
        bigben->hid = hid;
+       bigben->removed = false;
 
        error = hid_parse(hid);
        if (error) {
@@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,
 
        INIT_WORK(&bigben->worker, bigben_worker);
 
-       error = input_ff_create_memless(hidinput->input, bigben,
+       error = input_ff_create_memless(hidinput->input, NULL,
                hid_bigben_play_effect);
        if (error)
-               return error;
+               goto error_hw_stop;
 
        name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
 
@@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
                        sizeof(struct led_classdev) + name_sz,
                        GFP_KERNEL
                );
-               if (!led)
-                       return -ENOMEM;
+               if (!led) {
+                       error = -ENOMEM;
+                       goto error_hw_stop;
+               }
                name = (void *)(&led[1]);
                snprintf(name, name_sz,
                        "%s:red:bigben%d",
@@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
                bigben->leds[n] = led;
                error = devm_led_classdev_register(&hid->dev, led);
                if (error)
-                       return error;
+                       goto error_hw_stop;
        }
 
        /* initial state: LED1 is on, no rumble effect */
@@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
        hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
 
        return 0;
+
+error_hw_stop:
+       hid_hw_stop(hid);
+       return error;
 }
 
 static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
index 851fe54..359616e 100644 (file)
@@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
 
        rsize = ((report->size - 1) >> 3) + 1;
 
-       if (rsize > HID_MAX_BUFFER_SIZE)
+       if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
+               rsize = HID_MAX_BUFFER_SIZE - 1;
+       else if (rsize > HID_MAX_BUFFER_SIZE)
                rsize = HID_MAX_BUFFER_SIZE;
 
        if (csize < rsize) {
index dddfca5..0b6ee1d 100644 (file)
@@ -193,8 +193,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
                goto cleanup;
 
        /* The pointer is not NULL when we resume from hibernation */
-       if (input_device->hid_desc != NULL)
-               kfree(input_device->hid_desc);
+       kfree(input_device->hid_desc);
        input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
 
        if (!input_device->hid_desc)
@@ -207,8 +206,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
        }
 
        /* The pointer is not NULL when we resume from hibernation */
-       if (input_device->report_desc != NULL)
-               kfree(input_device->report_desc);
+       kfree(input_device->report_desc);
        input_device->report_desc = kzalloc(input_device->report_desc_size,
                                          GFP_ATOMIC);
 
index c436e12..6c55682 100644 (file)
@@ -41,8 +41,9 @@ static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
        /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
-       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
-                        USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
+       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+                    USB_VENDOR_ID_SYNAPTICS,
+                    USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index 70e1cb9..094f4f1 100644 (file)
@@ -1256,36 +1256,35 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
 {
        int status;
 
-       long charge_sts = (long)data[2];
+       long flags = (long) data[2];
 
-       *level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
-       switch (data[2] & 0xe0) {
-       case 0x00:
-               status = POWER_SUPPLY_STATUS_CHARGING;
-               break;
-       case 0x20:
-               status = POWER_SUPPLY_STATUS_FULL;
-               *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-               break;
-       case 0x40:
+       if (flags & 0x80)
+               switch (flags & 0x07) {
+               case 0:
+                       status = POWER_SUPPLY_STATUS_CHARGING;
+                       break;
+               case 1:
+                       status = POWER_SUPPLY_STATUS_FULL;
+                       *level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+                       break;
+               case 2:
+                       status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       break;
+               default:
+                       status = POWER_SUPPLY_STATUS_UNKNOWN;
+                       break;
+               }
+       else
                status = POWER_SUPPLY_STATUS_DISCHARGING;
-               break;
-       case 0xe0:
-               status = POWER_SUPPLY_STATUS_NOT_CHARGING;
-               break;
-       default:
-               status = POWER_SUPPLY_STATUS_UNKNOWN;
-       }
 
        *charge_type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
-       if (test_bit(3, &charge_sts)) {
+       if (test_bit(3, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
        }
-       if (test_bit(4, &charge_sts)) {
+       if (test_bit(4, &flags)) {
                *charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
        }
-
-       if (test_bit(5, &charge_sts)) {
+       if (test_bit(5, &flags)) {
                *level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
        }
 
index d31ea82..a66f080 100644 (file)
@@ -342,6 +342,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
                .driver_data = (void *)&sipodev_desc
        },
        {
+               .ident = "Trekstor SURFBOOK E11B",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
+               },
+               .driver_data = (void *)&sipodev_desc
+       },
+       {
                .ident = "Direkt-Tek DTLAPY116-2",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
index a970b80..4140dea 100644 (file)
@@ -932,9 +932,9 @@ void hiddev_disconnect(struct hid_device *hid)
        hiddev->exist = 0;
 
        if (hiddev->open) {
-               mutex_unlock(&hiddev->existancelock);
                hid_hw_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
+               mutex_unlock(&hiddev->existancelock);
        } else {
                mutex_unlock(&hiddev->existancelock);
                kfree(hiddev);
index 9632e2e..319a051 100644 (file)
@@ -413,7 +413,7 @@ static int ADT7462_REG_VOLT(struct adt7462_data *data, int which)
                        return 0x95;
                break;
        }
-       return -ENODEV;
+       return 0;
 }
 
 /* Provide labels for sysfs */
index ecd9b65..660556b 100644 (file)
 #define XDPE122_AMD_625MV              0x10 /* AMD mode 6.25mV */
 #define XDPE122_PAGE_NUM               2
 
+static int xdpe122_read_word_data(struct i2c_client *client, int page, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       long val;
+       s16 exponent;
+       s32 mantissa;
+       int ret;
+
+       switch (reg) {
+       case PMBUS_VOUT_OV_FAULT_LIMIT:
+       case PMBUS_VOUT_UV_FAULT_LIMIT:
+               ret = pmbus_read_word_data(client, page, reg);
+               if (ret < 0)
+                       return ret;
+
+               /* Convert register value to LINEAR11 data. */
+               exponent = ((s16)ret) >> 11;
+               mantissa = ((s16)((ret & GENMASK(10, 0)) << 5)) >> 5;
+               val = mantissa * 1000L;
+               if (exponent >= 0)
+                       val <<= exponent;
+               else
+                       val >>= -exponent;
+
+               /* Convert data to VID register. */
+               switch (info->vrm_version[page]) {
+               case vr13:
+                       if (val >= 500)
+                               return 1 + DIV_ROUND_CLOSEST(val - 500, 10);
+                       return 0;
+               case vr12:
+                       if (val >= 250)
+                               return 1 + DIV_ROUND_CLOSEST(val - 250, 5);
+                       return 0;
+               case imvp9:
+                       if (val >= 200)
+                               return 1 + DIV_ROUND_CLOSEST(val - 200, 10);
+                       return 0;
+               case amd625mv:
+                       if (val >= 200 && val <= 1550)
+                               return DIV_ROUND_CLOSEST((1550 - val) * 100,
+                                                        625);
+                       return 0;
+               default:
+                       return -EINVAL;
+               }
+       default:
+               return -ENODATA;
+       }
+
+       return 0;
+}
+
 static int xdpe122_identify(struct i2c_client *client,
                            struct pmbus_driver_info *info)
 {
@@ -70,6 +123,7 @@ static struct pmbus_driver_info xdpe122_info = {
                PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
                PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
        .identify = xdpe122_identify,
+       .read_word_data = xdpe122_read_word_data,
 };
 
 static int xdpe122_probe(struct i2c_client *client,
index 5255d37..1de23b4 100644 (file)
@@ -171,7 +171,7 @@ static void altr_i2c_init(struct altr_i2c_dev *idev)
        /* SCL Low Time */
        writel(t_low, idev->base + ALTR_I2C_SCL_LOW);
        /* SDA Hold Time, 300ns */
-       writel(div_u64(300 * clk_mhz, 1000), idev->base + ALTR_I2C_SDA_HOLD);
+       writel(3 * clk_mhz / 10, idev->base + ALTR_I2C_SDA_HOLD);
 
        /* Mask all master interrupt bits */
        altr_i2c_int_enable(idev, ALTR_I2C_ALL_IRQ, false);
index 16a67a6..b426fc9 100644 (file)
 
 #define X1000_I2C_DC_STOP              BIT(9)
 
-static const char * const jz4780_i2c_abrt_src[] = {
-       "ABRT_7B_ADDR_NOACK",
-       "ABRT_10ADDR1_NOACK",
-       "ABRT_10ADDR2_NOACK",
-       "ABRT_XDATA_NOACK",
-       "ABRT_GCALL_NOACK",
-       "ABRT_GCALL_READ",
-       "ABRT_HS_ACKD",
-       "SBYTE_ACKDET",
-       "ABRT_HS_NORSTRT",
-       "SBYTE_NORSTRT",
-       "ABRT_10B_RD_NORSTRT",
-       "ABRT_MASTER_DIS",
-       "ARB_LOST",
-       "SLVFLUSH_TXFIFO",
-       "SLV_ARBLOST",
-       "SLVRD_INTX",
-};
-
 #define JZ4780_I2C_INTST_IGC           BIT(11)
 #define JZ4780_I2C_INTST_ISTT          BIT(10)
 #define JZ4780_I2C_INTST_ISTP          BIT(9)
@@ -576,21 +557,8 @@ done:
 
 static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src)
 {
-       int i;
-
-       dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src);
-       dev_err(&i2c->adap.dev, "device addr=%x\n",
-               jz4780_i2c_readw(i2c, JZ4780_I2C_TAR));
-       dev_err(&i2c->adap.dev, "send cmd count:%d  %d\n",
-               i2c->cmd, i2c->cmd_buf[i2c->cmd]);
-       dev_err(&i2c->adap.dev, "receive data count:%d  %d\n",
-               i2c->cmd, i2c->data_buf[i2c->cmd]);
-
-       for (i = 0; i < 16; i++) {
-               if (src & BIT(i))
-                       dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n",
-                               i, jz4780_i2c_abrt_src[i]);
-       }
+       dev_dbg(&i2c->adap.dev, "txabrt: 0x%08x, cmd: %d, send: %d, recv: %d\n",
+               src, i2c->cmd, i2c->cmd_buf[i2c->cmd], i2c->data_buf[i2c->cmd]);
 }
 
 static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c,
index 1bb99b5..05c2698 100644 (file)
@@ -361,7 +361,7 @@ static const struct block_device_operations ide_gd_ops = {
        .release                = ide_gd_release,
        .ioctl                  = ide_gd_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl                  = ide_gd_compat_ioctl,
+       .compat_ioctl           = ide_gd_compat_ioctl,
 #endif
        .getgeo                 = ide_gd_getgeo,
        .check_events           = ide_gd_check_events,
index 68cc1b2..15e99a8 100644 (file)
@@ -1191,6 +1191,7 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device,
                        /* Sharing an ib_cm_id with different handlers is not
                         * supported */
                        spin_unlock_irqrestore(&cm.lock, flags);
+                       ib_destroy_cm_id(cm_id);
                        return ERR_PTR(-EINVAL);
                }
                refcount_inc(&cm_id_priv->refcount);
index 72f0321..2dec3a0 100644 (file)
@@ -3212,19 +3212,26 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
        int ret;
 
        id_priv = container_of(id, struct rdma_id_private, id);
+       memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
        if (id_priv->state == RDMA_CM_IDLE) {
                ret = cma_bind_addr(id, src_addr, dst_addr);
-               if (ret)
+               if (ret) {
+                       memset(cma_dst_addr(id_priv), 0,
+                              rdma_addr_size(dst_addr));
                        return ret;
+               }
        }
 
-       if (cma_family(id_priv) != dst_addr->sa_family)
+       if (cma_family(id_priv) != dst_addr->sa_family) {
+               memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
                return -EINVAL;
+       }
 
-       if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY))
+       if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) {
+               memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
                return -EINVAL;
+       }
 
-       memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
        if (cma_any_addr(dst_addr)) {
                ret = cma_resolve_loopback(id_priv);
        } else {
index b1457b3..cf42acc 100644 (file)
@@ -338,6 +338,20 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,
        qp->pd = pd;
        qp->uobject = uobj;
        qp->real_qp = qp;
+
+       qp->qp_type = attr->qp_type;
+       qp->rwq_ind_tbl = attr->rwq_ind_tbl;
+       qp->send_cq = attr->send_cq;
+       qp->recv_cq = attr->recv_cq;
+       qp->srq = attr->srq;
+       qp->rwq_ind_tbl = attr->rwq_ind_tbl;
+       qp->event_handler = attr->event_handler;
+
+       atomic_set(&qp->usecnt, 0);
+       spin_lock_init(&qp->mr_lock);
+       INIT_LIST_HEAD(&qp->rdma_mrs);
+       INIT_LIST_HEAD(&qp->sig_mrs);
+
        /*
         * We don't track XRC QPs for now, because they don't have PD
         * and more importantly they are created internaly by driver,
index ade7182..da8adad 100644 (file)
@@ -159,8 +159,10 @@ static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv)
 {
        struct list_head *e, *tmp;
 
-       list_for_each_safe(e, tmp, &cm_id_priv->work_free_list)
+       list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) {
+               list_del(e);
                kfree(list_entry(e, struct iwcm_work, free_list));
+       }
 }
 
 static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
index 37b433a..e0b0a91 100644 (file)
@@ -1757,6 +1757,8 @@ static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
                if (ret)
                        goto err_msg;
        } else {
+               if (!tb[RDMA_NLDEV_ATTR_RES_LQPN])
+                       goto err_msg;
                qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
                if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {
                        cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
index 4fad732..06e5b67 100644 (file)
@@ -273,6 +273,23 @@ static int rdma_rw_init_single_wr(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
        return 1;
 }
 
+static void rdma_rw_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
+                            u32 sg_cnt, enum dma_data_direction dir)
+{
+       if (is_pci_p2pdma_page(sg_page(sg)))
+               pci_p2pdma_unmap_sg(dev->dma_device, sg, sg_cnt, dir);
+       else
+               ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+}
+
+static int rdma_rw_map_sg(struct ib_device *dev, struct scatterlist *sg,
+                         u32 sg_cnt, enum dma_data_direction dir)
+{
+       if (is_pci_p2pdma_page(sg_page(sg)))
+               return pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir);
+       return ib_dma_map_sg(dev, sg, sg_cnt, dir);
+}
+
 /**
  * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context
  * @ctx:       context to initialize
@@ -295,11 +312,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
        struct ib_device *dev = qp->pd->device;
        int ret;
 
-       if (is_pci_p2pdma_page(sg_page(sg)))
-               ret = pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir);
-       else
-               ret = ib_dma_map_sg(dev, sg, sg_cnt, dir);
-
+       ret = rdma_rw_map_sg(dev, sg, sg_cnt, dir);
        if (!ret)
                return -ENOMEM;
        sg_cnt = ret;
@@ -338,7 +351,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
        return ret;
 
 out_unmap_sg:
-       ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+       rdma_rw_unmap_sg(dev, sg, sg_cnt, dir);
        return ret;
 }
 EXPORT_SYMBOL(rdma_rw_ctx_init);
@@ -588,11 +601,7 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
                break;
        }
 
-       if (is_pci_p2pdma_page(sg_page(sg)))
-               pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg,
-                                   sg_cnt, dir);
-       else
-               ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
+       rdma_rw_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 }
 EXPORT_SYMBOL(rdma_rw_ctx_destroy);
 
index 2b4d803..2d56083 100644 (file)
@@ -340,15 +340,19 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,
                return NULL;
 
        if (qp_attr_mask & IB_QP_PORT)
-               new_pps->main.port_num =
-                       (qp_pps) ? qp_pps->main.port_num : qp_attr->port_num;
+               new_pps->main.port_num = qp_attr->port_num;
+       else if (qp_pps)
+               new_pps->main.port_num = qp_pps->main.port_num;
+
        if (qp_attr_mask & IB_QP_PKEY_INDEX)
-               new_pps->main.pkey_index = (qp_pps) ? qp_pps->main.pkey_index :
-                                                     qp_attr->pkey_index;
+               new_pps->main.pkey_index = qp_attr->pkey_index;
+       else if (qp_pps)
+               new_pps->main.pkey_index = qp_pps->main.pkey_index;
+
        if ((qp_attr_mask & IB_QP_PKEY_INDEX) && (qp_attr_mask & IB_QP_PORT))
                new_pps->main.state = IB_PORT_PKEY_VALID;
 
-       if (!(qp_attr_mask & (IB_QP_PKEY_INDEX || IB_QP_PORT)) && qp_pps) {
+       if (!(qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) && qp_pps) {
                new_pps->main.port_num = qp_pps->main.port_num;
                new_pps->main.pkey_index = qp_pps->main.pkey_index;
                if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)
index b8c657b..cd656ad 100644 (file)
@@ -181,14 +181,28 @@ ib_umem_odp_alloc_child(struct ib_umem_odp *root, unsigned long addr,
        odp_data->page_shift = PAGE_SHIFT;
        odp_data->notifier.ops = ops;
 
+       /*
+        * A mmget must be held when registering a notifier, the owming_mm only
+        * has a mm_grab at this point.
+        */
+       if (!mmget_not_zero(umem->owning_mm)) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+
        odp_data->tgid = get_pid(root->tgid);
        ret = ib_init_umem_odp(odp_data, ops);
-       if (ret) {
-               put_pid(odp_data->tgid);
-               kfree(odp_data);
-               return ERR_PTR(ret);
-       }
+       if (ret)
+               goto out_tgid;
+       mmput(umem->owning_mm);
        return odp_data;
+
+out_tgid:
+       put_pid(odp_data->tgid);
+       mmput(umem->owning_mm);
+out_free:
+       kfree(odp_data);
+       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(ib_umem_odp_alloc_child);
 
index 0259337..060b4eb 100644 (file)
@@ -1445,16 +1445,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
                if (ret)
                        goto err_cb;
 
-               qp->pd            = pd;
-               qp->send_cq       = attr.send_cq;
-               qp->recv_cq       = attr.recv_cq;
-               qp->srq           = attr.srq;
-               qp->rwq_ind_tbl   = ind_tbl;
-               qp->event_handler = attr.event_handler;
-               qp->qp_type       = attr.qp_type;
-               atomic_set(&qp->usecnt, 0);
                atomic_inc(&pd->usecnt);
-               qp->port = 0;
                if (attr.send_cq)
                        atomic_inc(&attr.send_cq->usecnt);
                if (attr.recv_cq)
index 3ebae3b..e62c9df 100644 (file)
@@ -1185,16 +1185,6 @@ struct ib_qp *ib_create_qp_user(struct ib_pd *pd,
        if (ret)
                goto err;
 
-       qp->qp_type    = qp_init_attr->qp_type;
-       qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
-
-       atomic_set(&qp->usecnt, 0);
-       qp->mrs_used = 0;
-       spin_lock_init(&qp->mr_lock);
-       INIT_LIST_HEAD(&qp->rdma_mrs);
-       INIT_LIST_HEAD(&qp->sig_mrs);
-       qp->port = 0;
-
        if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
                struct ib_qp *xrc_qp =
                        create_xrc_qp_user(qp, qp_init_attr, udata);
index 089e201..2f6323a 100644 (file)
@@ -515,10 +515,11 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
                                       opa_get_lid(packet->dlid, 9B));
                if (!mcast)
                        goto drop;
+               rcu_read_lock();
                list_for_each_entry_rcu(p, &mcast->qp_list, list) {
                        packet->qp = p->qp;
                        if (hfi1_do_pkey_check(packet))
-                               goto drop;
+                               goto unlock_drop;
                        spin_lock_irqsave(&packet->qp->r_lock, flags);
                        packet_handler = qp_ok(packet);
                        if (likely(packet_handler))
@@ -527,6 +528,7 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
                                ibp->rvp.n_pkt_drops++;
                        spin_unlock_irqrestore(&packet->qp->r_lock, flags);
                }
+               rcu_read_unlock();
                /*
                 * Notify rvt_multicast_detach() if it is waiting for us
                 * to finish.
index d9bffcc..bb78142 100644 (file)
@@ -636,6 +636,7 @@ struct mlx5_ib_mr {
 
        /* For ODP and implicit */
        atomic_t                num_deferred_work;
+       wait_queue_head_t       q_deferred_work;
        struct xarray           implicit_children;
        union {
                struct rcu_head rcu;
index 4216814..bf50cd9 100644 (file)
@@ -235,7 +235,8 @@ static void free_implicit_child_mr(struct mlx5_ib_mr *mr, bool need_imr_xlt)
        mr->parent = NULL;
        mlx5_mr_cache_free(mr->dev, mr);
        ib_umem_odp_release(odp);
-       atomic_dec(&imr->num_deferred_work);
+       if (atomic_dec_and_test(&imr->num_deferred_work))
+               wake_up(&imr->q_deferred_work);
 }
 
 static void free_implicit_child_mr_work(struct work_struct *work)
@@ -554,6 +555,7 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
        imr->umem = &umem_odp->umem;
        imr->is_odp_implicit = true;
        atomic_set(&imr->num_deferred_work, 0);
+       init_waitqueue_head(&imr->q_deferred_work);
        xa_init(&imr->implicit_children);
 
        err = mlx5_ib_update_xlt(imr, 0,
@@ -611,10 +613,7 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
         * under xa_lock while the child is in the xarray. Thus at this point
         * it is only decreasing, and all work holding it is now on the wq.
         */
-       if (atomic_read(&imr->num_deferred_work)) {
-               flush_workqueue(system_unbound_wq);
-               WARN_ON(atomic_read(&imr->num_deferred_work));
-       }
+       wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work));
 
        /*
         * Fence the imr before we destroy the children. This allows us to
@@ -645,10 +644,7 @@ void mlx5_ib_fence_odp_mr(struct mlx5_ib_mr *mr)
        /* Wait for all running page-fault handlers to finish. */
        synchronize_srcu(&mr->dev->odp_srcu);
 
-       if (atomic_read(&mr->num_deferred_work)) {
-               flush_workqueue(system_unbound_wq);
-               WARN_ON(atomic_read(&mr->num_deferred_work));
-       }
+       wait_event(mr->q_deferred_work, !atomic_read(&mr->num_deferred_work));
 
        dma_fence_odp_mr(mr);
 }
@@ -1720,7 +1716,8 @@ static void destroy_prefetch_work(struct prefetch_mr_work *work)
        u32 i;
 
        for (i = 0; i < work->num_sge; ++i)
-               atomic_dec(&work->frags[i].mr->num_deferred_work);
+               if (atomic_dec_and_test(&work->frags[i].mr->num_deferred_work))
+                       wake_up(&work->frags[i].mr->q_deferred_work);
        kvfree(work);
 }
 
index 33778d4..5ef93f8 100644 (file)
@@ -329,8 +329,10 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
                if (mcast == NULL)
                        goto drop;
                this_cpu_inc(ibp->pmastats->n_multicast_rcv);
+               rcu_read_lock();
                list_for_each_entry_rcu(p, &mcast->qp_list, list)
                        qib_qp_rcv(rcd, hdr, 1, data, tlen, p->qp);
+               rcu_read_unlock();
                /*
                 * Notify rvt_multicast_detach() if it is waiting for us
                 * to finish.
index 96ed349..5cd40fb 100644 (file)
@@ -388,6 +388,9 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
                { .max_segment_size = SZ_2G };
        base_dev->num_comp_vectors = num_possible_cpus();
 
+       xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1);
+       xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1);
+
        ib_set_device_ops(base_dev, &siw_device_ops);
        rv = ib_device_set_netdev(base_dev, netdev, 1);
        if (rv)
@@ -415,9 +418,6 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
        sdev->attrs.max_srq_wr = SIW_MAX_SRQ_WR;
        sdev->attrs.max_srq_sge = SIW_MAX_SGE;
 
-       xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1);
-       xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1);
-
        INIT_LIST_HEAD(&sdev->cep_list);
        INIT_LIST_HEAD(&sdev->qp_list);
 
index f277e46..2c6515e 100644 (file)
@@ -445,6 +445,11 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
                path->name = kasprintf(GFP_KERNEL, "%s-%s",
                                       src_node->name, dst_node->name);
 
+       if (!path->name) {
+               kfree(path);
+               return ERR_PTR(-ENOMEM);
+       }
+
        return path;
 }
 EXPORT_SYMBOL_GPL(of_icc_get);
@@ -579,6 +584,10 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
        }
 
        path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
+       if (!path->name) {
+               kfree(path);
+               path = ERR_PTR(-ENOMEM);
+       }
 out:
        mutex_unlock(&icc_lock);
        return path;
index 8c74457..a0d87ed 100644 (file)
@@ -300,9 +300,11 @@ static int control_loop(void *dummy)
 /*     i2c probing and setup                                           */
 /************************************************************************/
 
-static int
-do_attach( struct i2c_adapter *adapter )
+static void do_attach(struct i2c_adapter *adapter)
 {
+       struct i2c_board_info info = { };
+       struct device_node *np;
+
        /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
        static const unsigned short scan_ds1775[] = {
                0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
@@ -313,25 +315,24 @@ do_attach( struct i2c_adapter *adapter )
                I2C_CLIENT_END
        };
 
-       if( strncmp(adapter->name, "uni-n", 5) )
-               return 0;
-
-       if( !x.running ) {
-               struct i2c_board_info info;
+       if (x.running || strncmp(adapter->name, "uni-n", 5))
+               return;
 
-               memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+       np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,ds1775");
+       if (np) {
+               of_node_put(np);
+       } else {
+               strlcpy(info.type, "MAC,ds1775", I2C_NAME_SIZE);
                i2c_new_probed_device(adapter, &info, scan_ds1775, NULL);
+       }
 
-               strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+       np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,adm1030");
+       if (np) {
+               of_node_put(np);
+       } else {
+               strlcpy(info.type, "MAC,adm1030", I2C_NAME_SIZE);
                i2c_new_probed_device(adapter, &info, scan_adm1030, NULL);
-
-               if( x.thermostat && x.fan ) {
-                       x.running = 1;
-                       x.poll_task = kthread_run(control_loop, NULL, "g4fand");
-               }
        }
-       return 0;
 }
 
 static int
@@ -404,8 +405,8 @@ out:
 enum chip { ds1775, adm1030 };
 
 static const struct i2c_device_id therm_windtunnel_id[] = {
-       { "therm_ds1775", ds1775 },
-       { "therm_adm1030", adm1030 },
+       { "MAC,ds1775", ds1775 },
+       { "MAC,adm1030", adm1030 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, therm_windtunnel_id);
@@ -414,6 +415,7 @@ static int
 do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = cl->adapter;
+       int ret = 0;
 
        if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
                                     | I2C_FUNC_SMBUS_WRITE_BYTE) )
@@ -421,11 +423,19 @@ do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 
        switch (id->driver_data) {
        case adm1030:
-               return attach_fan( cl );
+               ret = attach_fan(cl);
+               break;
        case ds1775:
-               return attach_thermostat(cl);
+               ret = attach_thermostat(cl);
+               break;
        }
-       return 0;
+
+       if (!x.running && x.thermostat && x.fan) {
+               x.running = 1;
+               x.poll_task = kthread_run(control_loop, NULL, "g4fand");
+       }
+
+       return ret;
 }
 
 static struct i2c_driver g4fan_driver = {
index c82578a..2ea0360 100644 (file)
 struct dm_bio_details {
        struct gendisk *bi_disk;
        u8 bi_partno;
+       int __bi_remaining;
        unsigned long bi_flags;
        struct bvec_iter bi_iter;
+       bio_end_io_t *bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       struct bio_integrity_payload *bi_integrity;
+#endif
 };
 
 static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
@@ -30,6 +35,11 @@ static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
        bd->bi_partno = bio->bi_partno;
        bd->bi_flags = bio->bi_flags;
        bd->bi_iter = bio->bi_iter;
+       bd->__bi_remaining = atomic_read(&bio->__bi_remaining);
+       bd->bi_end_io = bio->bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       bd->bi_integrity = bio_integrity(bio);
+#endif
 }
 
 static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
@@ -38,6 +48,11 @@ static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
        bio->bi_partno = bd->bi_partno;
        bio->bi_flags = bd->bi_flags;
        bio->bi_iter = bd->bi_iter;
+       atomic_set(&bio->__bi_remaining, bd->__bi_remaining);
+       bio->bi_end_io = bd->bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       bio->bi_integrity = bd->bi_integrity;
+#endif
 }
 
 #endif
index 2d32821..d3bb355 100644 (file)
@@ -2846,8 +2846,8 @@ static void cache_postsuspend(struct dm_target *ti)
        prevent_background_work(cache);
        BUG_ON(atomic_read(&cache->nr_io_migrations));
 
-       cancel_delayed_work(&cache->waker);
-       flush_workqueue(cache->wq);
+       cancel_delayed_work_sync(&cache->waker);
+       drain_workqueue(cache->wq);
        WARN_ON(cache->tracker.in_flight);
 
        /*
@@ -3492,7 +3492,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type cache_target = {
        .name = "cache",
-       .version = {2, 1, 0},
+       .version = {2, 2, 0},
        .module = THIS_MODULE,
        .ctr = cache_ctr,
        .dtr = cache_dtr,
index b225b3e..2f03fec 100644 (file)
@@ -6,6 +6,8 @@
  * This file is released under the GPL.
  */
 
+#include "dm-bio-record.h"
+
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/device-mapper.h>
@@ -201,17 +203,19 @@ struct dm_integrity_c {
        __u8 log2_blocks_per_bitmap_bit;
 
        unsigned char mode;
-       int suspending;
 
        int failed;
 
        struct crypto_shash *internal_hash;
 
+       struct dm_target *ti;
+
        /* these variables are locked with endio_wait.lock */
        struct rb_root in_progress;
        struct list_head wait_list;
        wait_queue_head_t endio_wait;
        struct workqueue_struct *wait_wq;
+       struct workqueue_struct *offload_wq;
 
        unsigned char commit_seq;
        commit_id_t commit_ids[N_COMMIT_IDS];
@@ -293,11 +297,7 @@ struct dm_integrity_io {
 
        struct completion *completion;
 
-       struct gendisk *orig_bi_disk;
-       u8 orig_bi_partno;
-       bio_end_io_t *orig_bi_end_io;
-       struct bio_integrity_payload *orig_bi_integrity;
-       struct bvec_iter orig_bi_iter;
+       struct dm_bio_details bio_details;
 };
 
 struct journal_completion {
@@ -1439,7 +1439,7 @@ static void dec_in_flight(struct dm_integrity_io *dio)
                        dio->range.logical_sector += dio->range.n_sectors;
                        bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT);
                        INIT_WORK(&dio->work, integrity_bio_wait);
-                       queue_work(ic->wait_wq, &dio->work);
+                       queue_work(ic->offload_wq, &dio->work);
                        return;
                }
                do_endio_flush(ic, dio);
@@ -1450,14 +1450,9 @@ static void integrity_end_io(struct bio *bio)
 {
        struct dm_integrity_io *dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io));
 
-       bio->bi_iter = dio->orig_bi_iter;
-       bio->bi_disk = dio->orig_bi_disk;
-       bio->bi_partno = dio->orig_bi_partno;
-       if (dio->orig_bi_integrity) {
-               bio->bi_integrity = dio->orig_bi_integrity;
+       dm_bio_restore(&dio->bio_details, bio);
+       if (bio->bi_integrity)
                bio->bi_opf |= REQ_INTEGRITY;
-       }
-       bio->bi_end_io = dio->orig_bi_end_io;
 
        if (dio->completion)
                complete(dio->completion);
@@ -1542,7 +1537,7 @@ static void integrity_metadata(struct work_struct *w)
                        }
                }
 
-               __bio_for_each_segment(bv, bio, iter, dio->orig_bi_iter) {
+               __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
                        unsigned pos;
                        char *mem, *checksums_ptr;
 
@@ -1586,7 +1581,7 @@ again:
                if (likely(checksums != checksums_onstack))
                        kfree(checksums);
        } else {
-               struct bio_integrity_payload *bip = dio->orig_bi_integrity;
+               struct bio_integrity_payload *bip = dio->bio_details.bi_integrity;
 
                if (bip) {
                        struct bio_vec biv;
@@ -1865,7 +1860,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map
 
        if (need_sync_io && from_map) {
                INIT_WORK(&dio->work, integrity_bio_wait);
-               queue_work(ic->metadata_wq, &dio->work);
+               queue_work(ic->offload_wq, &dio->work);
                return;
        }
 
@@ -2005,20 +2000,13 @@ offload_to_thread:
        } else
                dio->completion = NULL;
 
-       dio->orig_bi_iter = bio->bi_iter;
-
-       dio->orig_bi_disk = bio->bi_disk;
-       dio->orig_bi_partno = bio->bi_partno;
+       dm_bio_record(&dio->bio_details, bio);
        bio_set_dev(bio, ic->dev->bdev);
-
-       dio->orig_bi_integrity = bio_integrity(bio);
        bio->bi_integrity = NULL;
        bio->bi_opf &= ~REQ_INTEGRITY;
-
-       dio->orig_bi_end_io = bio->bi_end_io;
        bio->bi_end_io = integrity_end_io;
-
        bio->bi_iter.bi_size = dio->range.n_sectors << SECTOR_SHIFT;
+
        generic_make_request(bio);
 
        if (need_sync_io) {
@@ -2315,7 +2303,7 @@ static void integrity_writer(struct work_struct *w)
        unsigned prev_free_sectors;
 
        /* the following test is not needed, but it tests the replay code */
-       if (READ_ONCE(ic->suspending) && !ic->meta_dev)
+       if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev)
                return;
 
        spin_lock_irq(&ic->endio_wait.lock);
@@ -2376,7 +2364,7 @@ static void integrity_recalc(struct work_struct *w)
 
 next_chunk:
 
-       if (unlikely(READ_ONCE(ic->suspending)))
+       if (unlikely(dm_suspended(ic->ti)))
                goto unlock_ret;
 
        range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
@@ -2501,7 +2489,7 @@ static void bitmap_block_work(struct work_struct *w)
                                    dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) {
                        remove_range(ic, &dio->range);
                        INIT_WORK(&dio->work, integrity_bio_wait);
-                       queue_work(ic->wait_wq, &dio->work);
+                       queue_work(ic->offload_wq, &dio->work);
                } else {
                        block_bitmap_op(ic, ic->journal, dio->range.logical_sector,
                                        dio->range.n_sectors, BITMAP_OP_SET);
@@ -2524,7 +2512,7 @@ static void bitmap_block_work(struct work_struct *w)
 
                remove_range(ic, &dio->range);
                INIT_WORK(&dio->work, integrity_bio_wait);
-               queue_work(ic->wait_wq, &dio->work);
+               queue_work(ic->offload_wq, &dio->work);
        }
 
        queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval);
@@ -2804,8 +2792,6 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
 
        del_timer_sync(&ic->autocommit_timer);
 
-       WRITE_ONCE(ic->suspending, 1);
-
        if (ic->recalc_wq)
                drain_workqueue(ic->recalc_wq);
 
@@ -2834,8 +2820,6 @@ static void dm_integrity_postsuspend(struct dm_target *ti)
 #endif
        }
 
-       WRITE_ONCE(ic->suspending, 0);
-
        BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
 
        ic->journal_uptodate = true;
@@ -2888,17 +2872,24 @@ static void dm_integrity_resume(struct dm_target *ti)
        } else {
                replay_journal(ic);
                if (ic->mode == 'B') {
-                       int mode;
                        ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
                        ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit;
                        r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
                        if (unlikely(r))
                                dm_integrity_io_error(ic, "writing superblock", r);
 
-                       mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR;
-                       block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode);
-                       block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode);
-                       block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode);
+                       block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+                       block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+                       block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+                       if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
+                           le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors) {
+                               block_bitmap_op(ic, ic->journal, le64_to_cpu(ic->sb->recalc_sector),
+                                               ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+                               block_bitmap_op(ic, ic->recalc_bitmap, le64_to_cpu(ic->sb->recalc_sector),
+                                               ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+                               block_bitmap_op(ic, ic->may_write_bitmap, le64_to_cpu(ic->sb->recalc_sector),
+                                               ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+                       }
                        rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
                                           ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
                }
@@ -2967,7 +2958,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
                        DMEMIT(" meta_device:%s", ic->meta_dev->name);
                if (ic->sectors_per_block != 1)
                        DMEMIT(" block_size:%u", ic->sectors_per_block << SECTOR_SHIFT);
-               if (ic->recalculate_flag)
+               if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
                        DMEMIT(" recalculate");
                DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS);
                DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
@@ -3623,6 +3614,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
        ti->private = ic;
        ti->per_io_data_size = sizeof(struct dm_integrity_io);
+       ic->ti = ti;
 
        ic->in_progress = RB_ROOT;
        INIT_LIST_HEAD(&ic->wait_list);
@@ -3836,6 +3828,14 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto bad;
        }
 
+       ic->offload_wq = alloc_workqueue("dm-integrity-offload", WQ_MEM_RECLAIM,
+                                         METADATA_WORKQUEUE_MAX_ACTIVE);
+       if (!ic->offload_wq) {
+               ti->error = "Cannot allocate workqueue";
+               r = -ENOMEM;
+               goto bad;
+       }
+
        ic->commit_wq = alloc_workqueue("dm-integrity-commit", WQ_MEM_RECLAIM, 1);
        if (!ic->commit_wq) {
                ti->error = "Cannot allocate workqueue";
@@ -4140,6 +4140,8 @@ static void dm_integrity_dtr(struct dm_target *ti)
                destroy_workqueue(ic->metadata_wq);
        if (ic->wait_wq)
                destroy_workqueue(ic->wait_wq);
+       if (ic->offload_wq)
+               destroy_workqueue(ic->offload_wq);
        if (ic->commit_wq)
                destroy_workqueue(ic->commit_wq);
        if (ic->writer_wq)
@@ -4200,7 +4202,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
 
 static struct target_type integrity_target = {
        .name                   = "integrity",
-       .version                = {1, 4, 0},
+       .version                = {1, 5, 0},
        .module                 = THIS_MODULE,
        .features               = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
        .ctr                    = dm_integrity_ctr,
index 2bc18c9..58fd137 100644 (file)
@@ -2053,7 +2053,7 @@ static int multipath_busy(struct dm_target *ti)
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
        .name = "multipath",
-       .version = {1, 13, 0},
+       .version = {1, 14, 0},
        .features = DM_TARGET_SINGLETON | DM_TARGET_IMMUTABLE |
                    DM_TARGET_PASSES_INTEGRITY,
        .module = THIS_MODULE,
index fc9947d..76b6b32 100644 (file)
@@ -960,9 +960,9 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
                        DMWARN("%s: __commit_transaction() failed, error = %d",
                               __func__, r);
        }
+       pmd_write_unlock(pmd);
        if (!pmd->fail_io)
                __destroy_persistent_data_objects(pmd);
-       pmd_write_unlock(pmd);
 
        kfree(pmd);
        return 0;
index 0d61e9c..eec9f25 100644 (file)
@@ -1221,7 +1221,7 @@ bad:
 
 static struct target_type verity_target = {
        .name           = "verity",
-       .version        = {1, 5, 0},
+       .version        = {1, 6, 0},
        .module         = THIS_MODULE,
        .ctr            = verity_ctr,
        .dtr            = verity_dtr,
index b9e27e3..a09bdc0 100644 (file)
@@ -625,6 +625,12 @@ static void writecache_add_to_freelist(struct dm_writecache *wc, struct wc_entry
        wc->freelist_size++;
 }
 
+static inline void writecache_verify_watermark(struct dm_writecache *wc)
+{
+       if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
+               queue_work(wc->writeback_wq, &wc->writeback_work);
+}
+
 static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc, sector_t expected_sector)
 {
        struct wc_entry *e;
@@ -650,8 +656,8 @@ static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc, s
                list_del(&e->lru);
        }
        wc->freelist_size--;
-       if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
-               queue_work(wc->writeback_wq, &wc->writeback_work);
+
+       writecache_verify_watermark(wc);
 
        return e;
 }
@@ -842,7 +848,7 @@ static void writecache_suspend(struct dm_target *ti)
        }
        wc_unlock(wc);
 
-       flush_workqueue(wc->writeback_wq);
+       drain_workqueue(wc->writeback_wq);
 
        wc_lock(wc);
        if (flush_on_suspend)
@@ -965,6 +971,8 @@ erase_this:
                writecache_commit_flushed(wc, false);
        }
 
+       writecache_verify_watermark(wc);
+
        wc_unlock(wc);
 }
 
@@ -2312,7 +2320,7 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
 
 static struct target_type writecache_target = {
        .name                   = "writecache",
-       .version                = {1, 1, 1},
+       .version                = {1, 2, 0},
        .module                 = THIS_MODULE,
        .ctr                    = writecache_ctr,
        .dtr                    = writecache_dtr,
index 70a1063..f4f83d3 100644 (file)
@@ -533,8 +533,9 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
 
        /* Get the BIO chunk work. If one is not active yet, create one */
        cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
-       if (!cw) {
-
+       if (cw) {
+               dmz_get_chunk_work(cw);
+       } else {
                /* Create a new chunk work */
                cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
                if (unlikely(!cw)) {
@@ -543,7 +544,7 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
                }
 
                INIT_WORK(&cw->work, dmz_chunk_work);
-               refcount_set(&cw->refcount, 0);
+               refcount_set(&cw->refcount, 1);
                cw->target = dmz;
                cw->chunk = chunk;
                bio_list_init(&cw->bio_list);
@@ -556,7 +557,6 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
        }
 
        bio_list_add(&cw->bio_list, bio);
-       dmz_get_chunk_work(cw);
 
        dmz_reclaim_bio_acc(dmz->reclaim);
        if (queue_work(dmz->chunk_wq, &cw->work))
@@ -967,7 +967,7 @@ static int dmz_iterate_devices(struct dm_target *ti,
 
 static struct target_type dmz_type = {
        .name            = "zoned",
-       .version         = {1, 0, 0},
+       .version         = {1, 1, 0},
        .features        = DM_TARGET_SINGLETON | DM_TARGET_ZONED_HM,
        .module          = THIS_MODULE,
        .ctr             = dmz_ctr,
index b89f07e..0413018 100644 (file)
@@ -1788,7 +1788,8 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
                         * With request-based DM we only need to check the
                         * top-level queue for congestion.
                         */
-                       r = md->queue->backing_dev_info->wb.state & bdi_bits;
+                       struct backing_dev_info *bdi = md->queue->backing_dev_info;
+                       r = bdi->wb.congested->state & bdi_bits;
                } else {
                        map = dm_get_live_table_fast(md);
                        if (map)
@@ -1854,15 +1855,6 @@ static const struct dax_operations dm_dax_ops;
 
 static void dm_wq_work(struct work_struct *work);
 
-static void dm_init_normal_md_queue(struct mapped_device *md)
-{
-       /*
-        * Initialize aspects of queue that aren't relevant for blk-mq
-        */
-       md->queue->backing_dev_info->congested_data = md;
-       md->queue->backing_dev_info->congested_fn = dm_any_congested;
-}
-
 static void cleanup_mapped_device(struct mapped_device *md)
 {
        if (md->wq)
@@ -2249,6 +2241,12 @@ struct queue_limits *dm_get_queue_limits(struct mapped_device *md)
 }
 EXPORT_SYMBOL_GPL(dm_get_queue_limits);
 
+static void dm_init_congested_fn(struct mapped_device *md)
+{
+       md->queue->backing_dev_info->congested_data = md;
+       md->queue->backing_dev_info->congested_fn = dm_any_congested;
+}
+
 /*
  * Setup the DM device's queue based on md's type
  */
@@ -2265,11 +2263,12 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
                        DMERR("Cannot initialize queue for request-based dm-mq mapped device");
                        return r;
                }
+               dm_init_congested_fn(md);
                break;
        case DM_TYPE_BIO_BASED:
        case DM_TYPE_DAX_BIO_BASED:
        case DM_TYPE_NVME_BIO_BASED:
-               dm_init_normal_md_queue(md);
+               dm_init_congested_fn(md);
                break;
        case DM_TYPE_NONE:
                WARN_ON_ONCE(true);
@@ -2368,6 +2367,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
        map = dm_get_live_table(md, &srcu_idx);
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
+               set_bit(DMF_SUSPENDED, &md->flags);
                dm_table_postsuspend_targets(map);
        }
        /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
index 7c429ce..668770e 100644 (file)
@@ -639,9 +639,9 @@ int media_get_pad_index(struct media_entity *entity, bool is_sink,
                return -EINVAL;
 
        for (i = 0; i < entity->num_pads; i++) {
-               if (entity->pads[i].flags == MEDIA_PAD_FL_SINK)
+               if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
                        pad_is_sink = true;
-               else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE)
+               else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
                        pad_is_sink = false;
                else
                        continue;       /* This is an error! */
index 3c93d92..b6e39fb 100644 (file)
@@ -27,17 +27,17 @@ static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = {
        { V4L2_PIX_FMT_BGR24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_RGB24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_HSV24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
-       { V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_ABGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_ARGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_BGRA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+       { V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
        { V4L2_PIX_FMT_RGBA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-       { V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
+       { V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_HSV},
        { V4L2_PIX_FMT_GREY,    1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB},
 };
 
@@ -175,22 +175,14 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf,
        case V4L2_PIX_FMT_RGB32:
        case V4L2_PIX_FMT_XRGB32:
        case V4L2_PIX_FMT_HSV32:
-               rf->cr = rf->luma + 1;
-               rf->cb = rf->cr + 2;
-               rf->luma += 2;
-               break;
-       case V4L2_PIX_FMT_BGR32:
-       case V4L2_PIX_FMT_XBGR32:
-               rf->cb = rf->luma;
-               rf->cr = rf->cb + 2;
-               rf->luma++;
-               break;
        case V4L2_PIX_FMT_ARGB32:
                rf->alpha = rf->luma;
                rf->cr = rf->luma + 1;
                rf->cb = rf->cr + 2;
                rf->luma += 2;
                break;
+       case V4L2_PIX_FMT_BGR32:
+       case V4L2_PIX_FMT_XBGR32:
        case V4L2_PIX_FMT_ABGR32:
                rf->cb = rf->luma;
                rf->cr = rf->cb + 2;
@@ -198,10 +190,6 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf,
                rf->alpha = rf->cr + 1;
                break;
        case V4L2_PIX_FMT_BGRX32:
-               rf->cb = rf->luma + 1;
-               rf->cr = rf->cb + 2;
-               rf->luma += 2;
-               break;
        case V4L2_PIX_FMT_BGRA32:
                rf->alpha = rf->luma;
                rf->cb = rf->luma + 1;
@@ -209,10 +197,6 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf,
                rf->luma += 2;
                break;
        case V4L2_PIX_FMT_RGBX32:
-               rf->cr = rf->luma;
-               rf->cb = rf->cr + 2;
-               rf->luma++;
-               break;
        case V4L2_PIX_FMT_RGBA32:
                rf->alpha = rf->luma + 3;
                rf->cr = rf->luma;
index afda438..0655aa9 100644 (file)
@@ -635,8 +635,6 @@ static void pulse8_cec_adap_free(struct cec_adapter *adap)
        cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
        cancel_work_sync(&pulse8->irq_work);
        cancel_work_sync(&pulse8->tx_work);
-       serio_close(pulse8->serio);
-       serio_set_drvdata(pulse8->serio, NULL);
        kfree(pulse8);
 }
 
@@ -652,6 +650,9 @@ static void pulse8_disconnect(struct serio *serio)
        struct pulse8 *pulse8 = serio_get_drvdata(serio);
 
        cec_unregister_adapter(pulse8->adap);
+       pulse8->serio = NULL;
+       serio_set_drvdata(serio, NULL);
+       serio_close(serio);
 }
 
 static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
@@ -840,6 +841,8 @@ static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
        serio_set_drvdata(serio, pulse8);
        INIT_WORK(&pulse8->irq_work, pulse8_irq_work_handler);
        INIT_WORK(&pulse8->tx_work, pulse8_tx_work_handler);
+       INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
+                         pulse8_ping_eeprom_work_handler);
        mutex_init(&pulse8->lock);
        spin_lock_init(&pulse8->msg_lock);
        pulse8->config_pending = false;
@@ -865,17 +868,16 @@ static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
                pulse8->restoring_config = true;
        }
 
-       INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
-                         pulse8_ping_eeprom_work_handler);
        schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
 
        return 0;
 
 close_serio:
+       pulse8->serio = NULL;
+       serio_set_drvdata(serio, NULL);
        serio_close(serio);
 delete_adap:
        cec_delete_adapter(pulse8->adap);
-       serio_set_drvdata(serio, NULL);
 free_device:
        kfree(pulse8);
        return err;
index 1afd9c6..cc34c5a 100644 (file)
@@ -880,12 +880,12 @@ int v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev,
                goto err_rel_entity1;
 
        /* Connect the three entities */
-       ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 1,
+       ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 0,
                        MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
        if (ret)
                goto err_rel_entity2;
 
-       ret = media_create_pad_link(&m2m_dev->proc, 0, &m2m_dev->sink, 0,
+       ret = media_create_pad_link(&m2m_dev->proc, 1, &m2m_dev->sink, 0,
                        MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
        if (ret)
                goto err_rm_links0;
index 25e5f24..5bdf574 100644 (file)
@@ -2112,8 +2112,8 @@ exit_done:
        return status;
 }
 
-static int altera_get_note(u8 *p, s32 program_size,
-                       s32 *offset, char *key, char *value, int length)
+static int altera_get_note(u8 *p, s32 program_size, s32 *offset,
+                          char *key, char *value, int keylen, int vallen)
 /*
  * Gets key and value of NOTE fields in the JBC file.
  * Can be called in two modes:  if offset pointer is NULL,
@@ -2170,7 +2170,7 @@ static int altera_get_note(u8 *p, s32 program_size,
                                                &p[note_table + (8 * i) + 4])];
 
                                if (value != NULL)
-                                       strlcpy(value, value_ptr, length);
+                                       strlcpy(value, value_ptr, vallen);
 
                        }
                }
@@ -2189,13 +2189,13 @@ static int altera_get_note(u8 *p, s32 program_size,
                                strlcpy(key, &p[note_strings +
                                                get_unaligned_be32(
                                                &p[note_table + (8 * i)])],
-                                       length);
+                                       keylen);
 
                        if (value != NULL)
                                strlcpy(value, &p[note_strings +
                                                get_unaligned_be32(
                                                &p[note_table + (8 * i) + 4])],
-                                       length);
+                                       vallen);
 
                        *offset = i + 1;
                }
@@ -2449,7 +2449,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
                        __func__, (format_version == 2) ? "Jam STAPL" :
                                                "pre-standardized Jam 1.1");
                while (altera_get_note((u8 *)fw->data, fw->size,
-                                       &offset, key, value, 256) == 0)
+                                       &offset, key, value, 32, 256) == 0)
                        printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n",
                                        __func__, key, value);
        }
index aa54d35..a971c4b 100644 (file)
@@ -1732,8 +1732,11 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
         * the erase operation does not exceed the max_busy_timeout, we should
         * use R1B response. Or we need to prevent the host from doing hw busy
         * detection, which is done by converting to a R1 response instead.
+        * Note, some hosts requires R1B, which also means they are on their own
+        * when it comes to deal with the busy timeout.
         */
-       if (card->host->max_busy_timeout &&
+       if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) &&
+           card->host->max_busy_timeout &&
            busy_timeout > card->host->max_busy_timeout) {
                cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
        } else {
index f6912de..de14b58 100644 (file)
@@ -1910,9 +1910,12 @@ static int mmc_sleep(struct mmc_host *host)
         * If the max_busy_timeout of the host is specified, validate it against
         * the sleep cmd timeout. A failure means we need to prevent the host
         * from doing hw busy detection, which is done by converting to a R1
-        * response instead of a R1B.
+        * response instead of a R1B. Note, some hosts requires R1B, which also
+        * means they are on their own when it comes to deal with the busy
+        * timeout.
         */
-       if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
+       if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
+           (timeout_ms > host->max_busy_timeout)) {
                cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
        } else {
                cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
index da425ee..e025604 100644 (file)
@@ -542,9 +542,11 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
         * If the max_busy_timeout of the host is specified, make sure it's
         * enough to fit the used timeout_ms. In case it's not, let's instruct
         * the host to avoid HW busy detection, by converting to a R1 response
-        * instead of a R1B.
+        * instead of a R1B. Note, some hosts requires R1B, which also means
+        * they are on their own when it comes to deal with the busy timeout.
         */
-       if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
+       if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
+           (timeout_ms > host->max_busy_timeout))
                use_r1b_resp = false;
 
        cmd.opcode = MMC_SWITCH;
index c3a160c..3955fa5 100644 (file)
@@ -1590,7 +1590,7 @@ static u32 sdhci_msm_cqe_irq(struct sdhci_host *host, u32 intmask)
        return 0;
 }
 
-void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
+static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
 {
        struct sdhci_host *host = mmc_priv(mmc);
        unsigned long flags;
index 8820531..c497817 100644 (file)
@@ -1192,6 +1192,9 @@ static int sdhci_omap_probe(struct platform_device *pdev)
        if (of_find_property(dev->of_node, "dmas", NULL))
                sdhci_switch_external_dma(host, true);
 
+       /* R1B responses is required to properly manage HW busy detection. */
+       mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+
        ret = sdhci_setup_host(host);
        if (ret)
                goto err_put_sync;
index 5eea8d7..ce15a05 100644 (file)
@@ -262,10 +262,26 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
        return 0;
 }
 
+static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
+{
+       int ret;
+
+       ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1,
+                                   PCI_IRQ_MSI | PCI_IRQ_MSIX);
+       if (ret < 0) {
+               pr_warn("%s: enable PCI MSI failed, error=%d\n",
+                      mmc_hostname(slot->host->mmc), ret);
+               return;
+       }
+
+       slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
+}
+
 static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
 {
        struct sdhci_host *host = slot->host;
 
+       gli_pcie_enable_msi(slot);
        slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
        sdhci_enable_v4_mode(host);
 
@@ -276,6 +292,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
 {
        struct sdhci_host *host = slot->host;
 
+       gli_pcie_enable_msi(slot);
        slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
        sdhci_enable_v4_mode(host);
 
index 403ac44..a25c3a4 100644 (file)
@@ -1552,6 +1552,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
        if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
                host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
+       /* R1B responses is required to properly manage HW busy detection. */
+       host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+
        tegra_sdhci_parse_dt(host);
 
        tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
index 1cc2cd8..c816985 100644 (file)
@@ -50,11 +50,6 @@ struct arp_pkt {
 };
 #pragma pack()
 
-static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
-{
-       return (struct arp_pkt *)skb_network_header(skb);
-}
-
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
                                      bool strict_match);
@@ -553,10 +548,11 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
        spin_unlock(&bond->mode_lock);
 }
 
-static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_choose_channel(struct sk_buff *skb,
+                                       struct bonding *bond,
+                                       const struct arp_pkt *arp)
 {
        struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-       struct arp_pkt *arp = arp_pkt(skb);
        struct slave *assigned_slave, *curr_active_slave;
        struct rlb_client_info *client_info;
        u32 hash_index = 0;
@@ -653,8 +649,12 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
  */
 static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 {
-       struct arp_pkt *arp = arp_pkt(skb);
        struct slave *tx_slave = NULL;
+       struct arp_pkt *arp;
+
+       if (!pskb_network_may_pull(skb, sizeof(*arp)))
+               return NULL;
+       arp = (struct arp_pkt *)skb_network_header(skb);
 
        /* Don't modify or load balance ARPs that do not originate locally
         * (e.g.,arrive via a bridge).
@@ -664,7 +664,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 
        if (arp->op_code == htons(ARPOP_REPLY)) {
                /* the arp must be sent on the selected rx channel */
-               tx_slave = rlb_choose_channel(skb, bond);
+               tx_slave = rlb_choose_channel(skb, bond, arp);
                if (tx_slave)
                        bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr,
                                          tx_slave->dev->addr_len);
@@ -676,7 +676,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
                 * When the arp reply is received the entry will be updated
                 * with the correct unicast address of the client.
                 */
-               tx_slave = rlb_choose_channel(skb, bond);
+               tx_slave = rlb_choose_channel(skb, bond, arp);
 
                /* The ARP reply packets must be delayed so that
                 * they can cancel out the influence of the ARP request.
index 6ee06a4..68834a2 100644 (file)
@@ -883,6 +883,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
                                = { .len = sizeof(struct can_bittiming) },
        [IFLA_CAN_DATA_BITTIMING_CONST]
                                = { .len = sizeof(struct can_bittiming_const) },
+       [IFLA_CAN_TERMINATION]  = { .type = NLA_U16 },
 };
 
 static int can_validate(struct nlattr *tb[], struct nlattr *data[],
index d195554..b0f5280 100644 (file)
@@ -69,8 +69,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
                /* Force link status for IMP port */
                reg = core_readl(priv, offset);
                reg |= (MII_SW_OR | LINK_STS);
-               if (priv->type == BCM7278_DEVICE_ID)
-                       reg |= GMII_SPEED_UP_2G;
+               reg &= ~GMII_SPEED_UP_2G;
                core_writel(priv, reg, offset);
 
                /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
index 8c92895..2f993e6 100644 (file)
@@ -2769,6 +2769,8 @@ static u64 mv88e6xxx_devlink_atu_bin_get(struct mv88e6xxx_chip *chip,
                goto unlock;
        }
 
+       occupancy &= MV88E6XXX_G2_ATU_STATS_MASK;
+
 unlock:
        mv88e6xxx_reg_unlock(chip);
 
index b016cc2..ca3a7a7 100644 (file)
@@ -278,13 +278,13 @@ int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip,
        switch (direction) {
        case MV88E6XXX_EGRESS_DIR_INGRESS:
                dest_port_chip = &chip->ingress_dest_port;
-               reg &= MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK;
+               reg &= ~MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK;
                reg |= port <<
                       __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK);
                break;
        case MV88E6XXX_EGRESS_DIR_EGRESS:
                dest_port_chip = &chip->egress_dest_port;
-               reg &= MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK;
+               reg &= ~MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK;
                reg |= port <<
                       __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
                break;
index 0150301..8fd4830 100644 (file)
@@ -1099,6 +1099,13 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
 {
        int err, irq, virq;
 
+       chip->g2_irq.masked = ~0;
+       mv88e6xxx_reg_lock(chip);
+       err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);
+       mv88e6xxx_reg_unlock(chip);
+       if (err)
+               return err;
+
        chip->g2_irq.domain = irq_domain_add_simple(
                chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
        if (!chip->g2_irq.domain)
@@ -1108,7 +1115,6 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
                irq_create_mapping(chip->g2_irq.domain, irq);
 
        chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
-       chip->g2_irq.masked = ~0;
 
        chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
                                            MV88E6XXX_G1_STS_IRQ_DEVICE);
index 03ba6d2..7edea57 100644 (file)
@@ -1741,7 +1741,8 @@ static void sja1105_teardown(struct dsa_switch *ds)
                if (!dsa_is_user_port(ds, port))
                        continue;
 
-               kthread_destroy_worker(sp->xmit_worker);
+               if (sp->xmit_worker)
+                       kthread_destroy_worker(sp->xmit_worker);
        }
 
        sja1105_tas_teardown(ds);
index e0611cb..15b31cd 100644 (file)
@@ -2135,7 +2135,7 @@ static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv,
                return -ENOSPC;
 
        index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX);
-       if (index > RXCHK_BRCM_TAG_MAX)
+       if (index >= RXCHK_BRCM_TAG_MAX)
                return -ENOSPC;
 
        /* Location is the classification ID, and index is the position
index fd6e0e4..c5c8eff 100644 (file)
@@ -10982,13 +10982,13 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
        struct bnxt *bp = netdev_priv(dev);
 
        if (netif_running(dev))
-               bnxt_close_nic(bp, false, false);
+               bnxt_close_nic(bp, true, false);
 
        dev->mtu = new_mtu;
        bnxt_set_ring_params(bp);
 
        if (netif_running(dev))
-               return bnxt_open_nic(bp, false, false);
+               return bnxt_open_nic(bp, true, false);
 
        return 0;
 }
@@ -11252,7 +11252,7 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp)
                }
        }
        if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
-               netdev_info(bp->dev, "Receive PF driver unload event!");
+               netdev_info(bp->dev, "Receive PF driver unload event!\n");
 }
 
 #else
@@ -11759,7 +11759,7 @@ static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[])
        u32 dw;
 
        if (!pos) {
-               netdev_info(bp->dev, "Unable do read adapter's DSN");
+               netdev_info(bp->dev, "Unable do read adapter's DSN\n");
                return -EOPNOTSUPP;
        }
 
index eec0168..d3c93cc 100644 (file)
@@ -641,14 +641,14 @@ static int bnxt_dl_params_register(struct bnxt *bp)
        rc = devlink_params_register(bp->dl, bnxt_dl_params,
                                     ARRAY_SIZE(bnxt_dl_params));
        if (rc) {
-               netdev_warn(bp->dev, "devlink_params_register failed. rc=%d",
+               netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
                            rc);
                return rc;
        }
        rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
                                          ARRAY_SIZE(bnxt_dl_port_params));
        if (rc) {
-               netdev_err(bp->dev, "devlink_port_params_register failed");
+               netdev_err(bp->dev, "devlink_port_params_register failed\n");
                devlink_params_unregister(bp->dl, bnxt_dl_params,
                                          ARRAY_SIZE(bnxt_dl_params));
                return rc;
@@ -679,7 +679,7 @@ int bnxt_dl_register(struct bnxt *bp)
        else
                dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
        if (!dl) {
-               netdev_warn(bp->dev, "devlink_alloc failed");
+               netdev_warn(bp->dev, "devlink_alloc failed\n");
                return -ENOMEM;
        }
 
@@ -692,7 +692,7 @@ int bnxt_dl_register(struct bnxt *bp)
 
        rc = devlink_register(dl, &bp->pdev->dev);
        if (rc) {
-               netdev_warn(bp->dev, "devlink_register failed. rc=%d", rc);
+               netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc);
                goto err_dl_free;
        }
 
@@ -704,7 +704,7 @@ int bnxt_dl_register(struct bnxt *bp)
                               sizeof(bp->dsn));
        rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id);
        if (rc) {
-               netdev_err(bp->dev, "devlink_port_register failed");
+               netdev_err(bp->dev, "devlink_port_register failed\n");
                goto err_dl_unreg;
        }
 
index 6171fa8..1f67e67 100644 (file)
@@ -2007,8 +2007,8 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
        struct hwrm_nvm_install_update_output *resp = bp->hwrm_cmd_resp_addr;
        struct hwrm_nvm_install_update_input install = {0};
        const struct firmware *fw;
-       int rc, hwrm_err = 0;
        u32 item_len;
+       int rc = 0;
        u16 index;
 
        bnxt_hwrm_fw_set_time(bp);
@@ -2028,7 +2028,7 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
        }
 
        if (fw->size > item_len) {
-               netdev_err(dev, "PKG insufficient update area in nvram: %lu",
+               netdev_err(dev, "PKG insufficient update area in nvram: %lu\n",
                           (unsigned long)fw->size);
                rc = -EFBIG;
        } else {
@@ -2052,15 +2052,14 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
                        memcpy(kmem, fw->data, fw->size);
                        modify.host_src_addr = cpu_to_le64(dma_handle);
 
-                       hwrm_err = hwrm_send_message(bp, &modify,
-                                                    sizeof(modify),
-                                                    FLASH_PACKAGE_TIMEOUT);
+                       rc = hwrm_send_message(bp, &modify, sizeof(modify),
+                                              FLASH_PACKAGE_TIMEOUT);
                        dma_free_coherent(&bp->pdev->dev, fw->size, kmem,
                                          dma_handle);
                }
        }
        release_firmware(fw);
-       if (rc || hwrm_err)
+       if (rc)
                goto err_exit;
 
        if ((install_type & 0xffff) == 0)
@@ -2069,20 +2068,19 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
        install.install_type = cpu_to_le32(install_type);
 
        mutex_lock(&bp->hwrm_cmd_lock);
-       hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
-                                     INSTALL_PACKAGE_TIMEOUT);
-       if (hwrm_err) {
+       rc = _hwrm_send_message(bp, &install, sizeof(install),
+                               INSTALL_PACKAGE_TIMEOUT);
+       if (rc) {
                u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
 
                if (resp->error_code && error_code ==
                    NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
                        install.flags |= cpu_to_le16(
                               NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
-                       hwrm_err = _hwrm_send_message(bp, &install,
-                                                     sizeof(install),
-                                                     INSTALL_PACKAGE_TIMEOUT);
+                       rc = _hwrm_send_message(bp, &install, sizeof(install),
+                                               INSTALL_PACKAGE_TIMEOUT);
                }
-               if (hwrm_err)
+               if (rc)
                        goto flash_pkg_exit;
        }
 
@@ -2094,7 +2092,7 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
 flash_pkg_exit:
        mutex_unlock(&bp->hwrm_cmd_lock);
 err_exit:
-       if (hwrm_err == -EACCES)
+       if (rc == -EACCES)
                bnxt_print_admin_err(bp);
        return rc;
 }
@@ -3338,7 +3336,7 @@ err:
        kfree(coredump.data);
        *dump_len += sizeof(struct bnxt_coredump_record);
        if (rc == -ENOBUFS)
-               netdev_err(bp->dev, "Firmware returned large coredump buffer");
+               netdev_err(bp->dev, "Firmware returned large coredump buffer\n");
        return rc;
 }
 
index 0cc6ec5..9bec256 100644 (file)
@@ -50,7 +50,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev)
 
        /* check if dev belongs to the same switch */
        if (!netdev_port_same_parent_id(pf_bp->dev, dev)) {
-               netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch",
+               netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch\n",
                            dev->ifindex);
                return BNXT_FID_INVALID;
        }
@@ -70,7 +70,7 @@ static int bnxt_tc_parse_redir(struct bnxt *bp,
        struct net_device *dev = act->dev;
 
        if (!dev) {
-               netdev_info(bp->dev, "no dev in mirred action");
+               netdev_info(bp->dev, "no dev in mirred action\n");
                return -EINVAL;
        }
 
@@ -106,7 +106,7 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
        const struct ip_tunnel_key *tun_key = &tun_info->key;
 
        if (ip_tunnel_info_af(tun_info) != AF_INET) {
-               netdev_info(bp->dev, "only IPv4 tunnel-encap is supported");
+               netdev_info(bp->dev, "only IPv4 tunnel-encap is supported\n");
                return -EOPNOTSUPP;
        }
 
@@ -295,7 +295,7 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
        int i, rc;
 
        if (!flow_action_has_entries(flow_action)) {
-               netdev_info(bp->dev, "no actions");
+               netdev_info(bp->dev, "no actions\n");
                return -EINVAL;
        }
 
@@ -370,7 +370,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
        /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
        if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
            (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
-               netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x",
+               netdev_info(bp->dev, "cannot form TC key: used_keys = 0x%x\n",
                            dissector->used_keys);
                return -EOPNOTSUPP;
        }
@@ -508,7 +508,7 @@ static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -841,7 +841,7 @@ static int hwrm_cfa_decap_filter_alloc(struct bnxt *bp,
                resp = bnxt_get_hwrm_resp_addr(bp, &req);
                *decap_filter_handle = resp->decap_filter_id;
        } else {
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -859,7 +859,7 @@ static int hwrm_cfa_decap_filter_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -906,7 +906,7 @@ static int hwrm_cfa_encap_record_alloc(struct bnxt *bp,
                resp = bnxt_get_hwrm_resp_addr(bp, &req);
                *encap_record_handle = resp->encap_record_id;
        } else {
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -924,7 +924,7 @@ static int hwrm_cfa_encap_record_free(struct bnxt *bp,
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -943,7 +943,7 @@ static int bnxt_tc_put_l2_node(struct bnxt *bp,
                                             tc_info->l2_ht_params);
                if (rc)
                        netdev_err(bp->dev,
-                                  "Error: %s: rhashtable_remove_fast: %d",
+                                  "Error: %s: rhashtable_remove_fast: %d\n",
                                   __func__, rc);
                kfree_rcu(l2_node, rcu);
        }
@@ -972,7 +972,7 @@ bnxt_tc_get_l2_node(struct bnxt *bp, struct rhashtable *l2_table,
                if (rc) {
                        kfree_rcu(l2_node, rcu);
                        netdev_err(bp->dev,
-                                  "Error: %s: rhashtable_insert_fast: %d",
+                                  "Error: %s: rhashtable_insert_fast: %d\n",
                                   __func__, rc);
                        return NULL;
                }
@@ -1031,7 +1031,7 @@ static bool bnxt_tc_can_offload(struct bnxt *bp, struct bnxt_tc_flow *flow)
        if ((flow->flags & BNXT_TC_FLOW_FLAGS_PORTS) &&
            (flow->l4_key.ip_proto != IPPROTO_TCP &&
             flow->l4_key.ip_proto != IPPROTO_UDP)) {
-               netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports",
+               netdev_info(bp->dev, "Cannot offload non-TCP/UDP (%d) ports\n",
                            flow->l4_key.ip_proto);
                return false;
        }
@@ -1088,7 +1088,7 @@ static int bnxt_tc_put_tunnel_node(struct bnxt *bp,
                rc =  rhashtable_remove_fast(tunnel_table, &tunnel_node->node,
                                             *ht_params);
                if (rc) {
-                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
+                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
                        rc = -1;
                }
                kfree_rcu(tunnel_node, rcu);
@@ -1129,7 +1129,7 @@ bnxt_tc_get_tunnel_node(struct bnxt *bp, struct rhashtable *tunnel_table,
        tunnel_node->refcount++;
        return tunnel_node;
 err:
-       netdev_info(bp->dev, "error rc=%d", rc);
+       netdev_info(bp->dev, "error rc=%d\n", rc);
        return NULL;
 }
 
@@ -1187,7 +1187,7 @@ static void bnxt_tc_put_decap_l2_node(struct bnxt *bp,
                                             &decap_l2_node->node,
                                             tc_info->decap_l2_ht_params);
                if (rc)
-                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d", rc);
+                       netdev_err(bp->dev, "rhashtable_remove_fast rc=%d\n", rc);
                kfree_rcu(decap_l2_node, rcu);
        }
 }
@@ -1227,7 +1227,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
        rt = ip_route_output_key(dev_net(real_dst_dev), &flow);
        if (IS_ERR(rt)) {
-               netdev_info(bp->dev, "no route to %pI4b", &flow.daddr);
+               netdev_info(bp->dev, "no route to %pI4b\n", &flow.daddr);
                return -EOPNOTSUPP;
        }
 
@@ -1241,7 +1241,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
                if (vlan->real_dev != real_dst_dev) {
                        netdev_info(bp->dev,
-                                   "dst_dev(%s) doesn't use PF-if(%s)",
+                                   "dst_dev(%s) doesn't use PF-if(%s)\n",
                                    netdev_name(dst_dev),
                                    netdev_name(real_dst_dev));
                        rc = -EOPNOTSUPP;
@@ -1253,7 +1253,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 #endif
        } else if (dst_dev != real_dst_dev) {
                netdev_info(bp->dev,
-                           "dst_dev(%s) for %pI4b is not PF-if(%s)",
+                           "dst_dev(%s) for %pI4b is not PF-if(%s)\n",
                            netdev_name(dst_dev), &flow.daddr,
                            netdev_name(real_dst_dev));
                rc = -EOPNOTSUPP;
@@ -1262,7 +1262,7 @@ static int bnxt_tc_resolve_tunnel_hdrs(struct bnxt *bp,
 
        nbr = dst_neigh_lookup(&rt->dst, &flow.daddr);
        if (!nbr) {
-               netdev_info(bp->dev, "can't lookup neighbor for %pI4b",
+               netdev_info(bp->dev, "can't lookup neighbor for %pI4b\n",
                            &flow.daddr);
                rc = -EOPNOTSUPP;
                goto put_rt;
@@ -1472,7 +1472,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
        rc = rhashtable_remove_fast(&tc_info->flow_table, &flow_node->node,
                                    tc_info->flow_ht_params);
        if (rc)
-               netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d",
+               netdev_err(bp->dev, "Error: %s: rhashtable_remove_fast rc=%d\n",
                           __func__, rc);
 
        kfree_rcu(flow_node, rcu);
@@ -1587,7 +1587,7 @@ unlock:
 free_node:
        kfree_rcu(new_node, rcu);
 done:
-       netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d",
+       netdev_err(bp->dev, "Error: %s: cookie=0x%lx error=%d\n",
                   __func__, tc_flow_cmd->cookie, rc);
        return rc;
 }
@@ -1700,7 +1700,7 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
                                                le64_to_cpu(resp_bytes[i]);
                }
        } else {
-               netdev_info(bp->dev, "error rc=%d", rc);
+               netdev_info(bp->dev, "error rc=%d\n", rc);
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -1970,7 +1970,7 @@ static int bnxt_tc_indr_block_event(struct notifier_block *nb,
                                                   bp);
                if (rc)
                        netdev_info(bp->dev,
-                                   "Failed to register indirect blk: dev: %s",
+                                   "Failed to register indirect blk: dev: %s\n",
                                    netdev->name);
                break;
        case NETDEV_UNREGISTER:
index b010b34..6f2faf8 100644 (file)
@@ -43,7 +43,7 @@ static int hwrm_cfa_vfr_alloc(struct bnxt *bp, u16 vf_idx,
                netdev_dbg(bp->dev, "tx_cfa_action=0x%x, rx_cfa_code=0x%x",
                           *tx_cfa_action, *rx_cfa_code);
        } else {
-               netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
        }
 
        mutex_unlock(&bp->hwrm_cmd_lock);
@@ -60,7 +60,7 @@ static int hwrm_cfa_vfr_free(struct bnxt *bp, u16 vf_idx)
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "%s error rc=%d", __func__, rc);
+               netdev_info(bp->dev, "%s error rc=%d\n", __func__, rc);
        return rc;
 }
 
@@ -465,7 +465,7 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
        return 0;
 
 err:
-       netdev_info(bp->dev, "%s error=%d", __func__, rc);
+       netdev_info(bp->dev, "%s error=%d\n", __func__, rc);
        kfree(cfa_code_map);
        __bnxt_vf_reps_destroy(bp);
        return rc;
@@ -488,7 +488,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
 
        mutex_lock(&bp->sriov_lock);
        if (bp->eswitch_mode == mode) {
-               netdev_info(bp->dev, "already in %s eswitch mode",
+               netdev_info(bp->dev, "already in %s eswitch mode\n",
                            mode == DEVLINK_ESWITCH_MODE_LEGACY ?
                            "legacy" : "switchdev");
                rc = -EINVAL;
@@ -508,7 +508,7 @@ int bnxt_dl_eswitch_mode_set(struct devlink *devlink, u16 mode,
                }
 
                if (pci_num_vf(bp->pdev) == 0) {
-                       netdev_info(bp->dev, "Enable VFs before setting switchdev mode");
+                       netdev_info(bp->dev, "Enable VFs before setting switchdev mode\n");
                        rc = -EPERM;
                        goto done;
                }
index 6392a25..1024494 100644 (file)
@@ -294,6 +294,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
         */
        if (priv->ext_phy) {
                reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
+               reg &= ~ID_MODE_DIS;
                reg |= id_mode_dis;
                if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
                        reg |= RGMII_MODE_EN_V123;
index 649842a..97f90ed 100644 (file)
@@ -5381,12 +5381,11 @@ static inline bool is_x_10g_port(const struct link_config *lc)
 static int cfg_queues(struct adapter *adap)
 {
        u32 avail_qsets, avail_eth_qsets, avail_uld_qsets;
+       u32 i, n10g = 0, qidx = 0, n1g = 0;
+       u32 ncpus = num_online_cpus();
        u32 niqflint, neq, num_ulds;
        struct sge *s = &adap->sge;
-       u32 i, n10g = 0, qidx = 0;
-#ifndef CONFIG_CHELSIO_T4_DCB
-       int q10g = 0;
-#endif
+       u32 q10g = 0, q1g;
 
        /* Reduce memory usage in kdump environment, disable all offload. */
        if (is_kdump_kernel() || (is_uld(adap) && t4_uld_mem_alloc(adap))) {
@@ -5424,44 +5423,50 @@ static int cfg_queues(struct adapter *adap)
                n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
 
        avail_eth_qsets = min_t(u32, avail_qsets, MAX_ETH_QSETS);
+
+       /* We default to 1 queue per non-10G port and up to # of cores queues
+        * per 10G port.
+        */
+       if (n10g)
+               q10g = (avail_eth_qsets - (adap->params.nports - n10g)) / n10g;
+
+       n1g = adap->params.nports - n10g;
 #ifdef CONFIG_CHELSIO_T4_DCB
        /* For Data Center Bridging support we need to be able to support up
         * to 8 Traffic Priorities; each of which will be assigned to its
         * own TX Queue in order to prevent Head-Of-Line Blocking.
         */
+       q1g = 8;
        if (adap->params.nports * 8 > avail_eth_qsets) {
                dev_err(adap->pdev_dev, "DCB avail_eth_qsets=%d < %d!\n",
                        avail_eth_qsets, adap->params.nports * 8);
                return -ENOMEM;
        }
 
-       for_each_port(adap, i) {
-               struct port_info *pi = adap2pinfo(adap, i);
+       if (adap->params.nports * ncpus < avail_eth_qsets)
+               q10g = max(8U, ncpus);
+       else
+               q10g = max(8U, q10g);
 
-               pi->first_qset = qidx;
-               pi->nqsets = is_kdump_kernel() ? 1 : 8;
-               qidx += pi->nqsets;
-       }
-#else /* !CONFIG_CHELSIO_T4_DCB */
-       /* We default to 1 queue per non-10G port and up to # of cores queues
-        * per 10G port.
-        */
-       if (n10g)
-               q10g = (avail_eth_qsets - (adap->params.nports - n10g)) / n10g;
-       if (q10g > netif_get_num_default_rss_queues())
-               q10g = netif_get_num_default_rss_queues();
+       while ((q10g * n10g) > (avail_eth_qsets - n1g * q1g))
+               q10g--;
 
-       if (is_kdump_kernel())
+#else /* !CONFIG_CHELSIO_T4_DCB */
+       q1g = 1;
+       q10g = min(q10g, ncpus);
+#endif /* !CONFIG_CHELSIO_T4_DCB */
+       if (is_kdump_kernel()) {
                q10g = 1;
+               q1g = 1;
+       }
 
        for_each_port(adap, i) {
                struct port_info *pi = adap2pinfo(adap, i);
 
                pi->first_qset = qidx;
-               pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
+               pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : q1g;
                qidx += pi->nqsets;
        }
-#endif /* !CONFIG_CHELSIO_T4_DCB */
 
        s->ethqsets = qidx;
        s->max_ethqsets = qidx;   /* MSI-X may lower it later */
@@ -5473,7 +5478,7 @@ static int cfg_queues(struct adapter *adap)
                 * capped by the number of available cores.
                 */
                num_ulds = adap->num_uld + adap->num_ofld_uld;
-               i = min_t(u32, MAX_OFLD_QSETS, num_online_cpus());
+               i = min_t(u32, MAX_OFLD_QSETS, ncpus);
                avail_uld_qsets = roundup(i, adap->params.nports);
                if (avail_qsets < num_ulds * adap->params.nports) {
                        adap->params.offload = 0;
index fd93d54..ca74a68 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright 2008 - 2016 Freescale Semiconductor Inc.
+ * Copyright 2020 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -123,7 +124,22 @@ MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
 #define FSL_QMAN_MAX_OAL       127
 
 /* Default alignment for start of data in an Rx FD */
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+/* aligning data start to 64 avoids DMA transaction splits, unless the buffer
+ * is crossing a 4k page boundary
+ */
+#define DPAA_FD_DATA_ALIGNMENT  (fman_has_errata_a050385() ? 64 : 16)
+/* aligning to 256 avoids DMA transaction splits caused by 4k page boundary
+ * crossings; also, all SG fragments except the last must have a size multiple
+ * of 256 to avoid DMA transaction splits
+ */
+#define DPAA_A050385_ALIGN 256
+#define DPAA_FD_RX_DATA_ALIGNMENT (fman_has_errata_a050385() ? \
+                                  DPAA_A050385_ALIGN : 16)
+#else
 #define DPAA_FD_DATA_ALIGNMENT  16
+#define DPAA_FD_RX_DATA_ALIGNMENT DPAA_FD_DATA_ALIGNMENT
+#endif
 
 /* The DPAA requires 256 bytes reserved and mapped for the SGT */
 #define DPAA_SGT_SIZE 256
@@ -158,8 +174,13 @@ MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
 #define DPAA_PARSE_RESULTS_SIZE sizeof(struct fman_prs_result)
 #define DPAA_TIME_STAMP_SIZE 8
 #define DPAA_HASH_RESULTS_SIZE 8
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+#define DPAA_RX_PRIV_DATA_SIZE (DPAA_A050385_ALIGN - (DPAA_PARSE_RESULTS_SIZE\
+        + DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE))
+#else
 #define DPAA_RX_PRIV_DATA_SIZE (u16)(DPAA_TX_PRIV_DATA_SIZE + \
                                        dpaa_rx_extra_headroom)
+#endif
 
 #define DPAA_ETH_PCD_RXQ_NUM   128
 
@@ -180,7 +201,12 @@ static struct dpaa_bp *dpaa_bp_array[BM_MAX_NUM_OF_POOLS];
 
 #define DPAA_BP_RAW_SIZE 4096
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+#define dpaa_bp_size(raw_size) (SKB_WITH_OVERHEAD(raw_size) & \
+                               ~(DPAA_A050385_ALIGN - 1))
+#else
 #define dpaa_bp_size(raw_size) SKB_WITH_OVERHEAD(raw_size)
+#endif
 
 static int dpaa_max_frm;
 
@@ -1192,7 +1218,7 @@ static int dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp *bp,
        buf_prefix_content.pass_prs_result = true;
        buf_prefix_content.pass_hash_result = true;
        buf_prefix_content.pass_time_stamp = true;
-       buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
+       buf_prefix_content.data_align = DPAA_FD_RX_DATA_ALIGNMENT;
 
        rx_p = &params.specific_params.rx_params;
        rx_p->err_fqid = errq->fqid;
@@ -1662,6 +1688,8 @@ static u8 rx_csum_offload(const struct dpaa_priv *priv, const struct qm_fd *fd)
        return CHECKSUM_NONE;
 }
 
+#define PTR_IS_ALIGNED(x, a) (IS_ALIGNED((unsigned long)(x), (a)))
+
 /* Build a linear skb around the received buffer.
  * We are guaranteed there is enough room at the end of the data buffer to
  * accommodate the shared info area of the skb.
@@ -1733,8 +1761,7 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
 
                sg_addr = qm_sg_addr(&sgt[i]);
                sg_vaddr = phys_to_virt(sg_addr);
-               WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
-                                   SMP_CACHE_BYTES));
+               WARN_ON(!PTR_IS_ALIGNED(sg_vaddr, SMP_CACHE_BYTES));
 
                dma_unmap_page(priv->rx_dma_dev, sg_addr,
                               DPAA_BP_RAW_SIZE, DMA_FROM_DEVICE);
@@ -2022,6 +2049,75 @@ static inline int dpaa_xmit(struct dpaa_priv *priv,
        return 0;
 }
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+int dpaa_a050385_wa(struct net_device *net_dev, struct sk_buff **s)
+{
+       struct dpaa_priv *priv = netdev_priv(net_dev);
+       struct sk_buff *new_skb, *skb = *s;
+       unsigned char *start, i;
+
+       /* check linear buffer alignment */
+       if (!PTR_IS_ALIGNED(skb->data, DPAA_A050385_ALIGN))
+               goto workaround;
+
+       /* linear buffers just need to have an aligned start */
+       if (!skb_is_nonlinear(skb))
+               return 0;
+
+       /* linear data size for nonlinear skbs needs to be aligned */
+       if (!IS_ALIGNED(skb_headlen(skb), DPAA_A050385_ALIGN))
+               goto workaround;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+               /* all fragments need to have aligned start addresses */
+               if (!IS_ALIGNED(skb_frag_off(frag), DPAA_A050385_ALIGN))
+                       goto workaround;
+
+               /* all but last fragment need to have aligned sizes */
+               if (!IS_ALIGNED(skb_frag_size(frag), DPAA_A050385_ALIGN) &&
+                   (i < skb_shinfo(skb)->nr_frags - 1))
+                       goto workaround;
+       }
+
+       return 0;
+
+workaround:
+       /* copy all the skb content into a new linear buffer */
+       new_skb = netdev_alloc_skb(net_dev, skb->len + DPAA_A050385_ALIGN - 1 +
+                                               priv->tx_headroom);
+       if (!new_skb)
+               return -ENOMEM;
+
+       /* NET_SKB_PAD bytes already reserved, adding up to tx_headroom */
+       skb_reserve(new_skb, priv->tx_headroom - NET_SKB_PAD);
+
+       /* Workaround for DPAA_A050385 requires data start to be aligned */
+       start = PTR_ALIGN(new_skb->data, DPAA_A050385_ALIGN);
+       if (start - new_skb->data != 0)
+               skb_reserve(new_skb, start - new_skb->data);
+
+       skb_put(new_skb, skb->len);
+       skb_copy_bits(skb, 0, new_skb->data, skb->len);
+       skb_copy_header(new_skb, skb);
+       new_skb->dev = skb->dev;
+
+       /* We move the headroom when we align it so we have to reset the
+        * network and transport header offsets relative to the new data
+        * pointer. The checksum offload relies on these offsets.
+        */
+       skb_set_network_header(new_skb, skb_network_offset(skb));
+       skb_set_transport_header(new_skb, skb_transport_offset(skb));
+
+       /* TODO: does timestamping need the result in the old skb? */
+       dev_kfree_skb(skb);
+       *s = new_skb;
+
+       return 0;
+}
+#endif
+
 static netdev_tx_t
 dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
 {
@@ -2068,6 +2164,14 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
                nonlinear = skb_is_nonlinear(skb);
        }
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+       if (unlikely(fman_has_errata_a050385())) {
+               if (dpaa_a050385_wa(net_dev, &skb))
+                       goto enomem;
+               nonlinear = skb_is_nonlinear(skb);
+       }
+#endif
+
        if (nonlinear) {
                /* Just create a S/G fd based on the skb */
                err = skb_to_sg_fd(priv, skb, &fd);
@@ -2741,9 +2845,7 @@ static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl)
        headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE +
                DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE);
 
-       return DPAA_FD_DATA_ALIGNMENT ? ALIGN(headroom,
-                                             DPAA_FD_DATA_ALIGNMENT) :
-                                       headroom;
+       return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT);
 }
 
 static int dpaa_eth_probe(struct platform_device *pdev)
index 4432a59..23c5fef 100644 (file)
@@ -2529,15 +2529,15 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
                return -EINVAL;
        }
 
-       cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr);
+       cycle = fec_enet_us_to_itr_clock(ndev, ec->rx_coalesce_usecs);
        if (cycle > 0xFFFF) {
                dev_err(dev, "Rx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
-       cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr);
+       cycle = fec_enet_us_to_itr_clock(ndev, ec->tx_coalesce_usecs);
        if (cycle > 0xFFFF) {
-               dev_err(dev, "Rx coalesced usec exceed hardware limitation\n");
+               dev_err(dev, "Tx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
index 0139cb9..3415018 100644 (file)
@@ -8,3 +8,31 @@ config FSL_FMAN
        help
                Freescale Data-Path Acceleration Architecture Frame Manager
                (FMan) support
+
+config DPAA_ERRATUM_A050385
+       bool
+       depends on ARM64 && FSL_DPAA
+       default y
+       help
+               DPAA FMan erratum A050385 software workaround implementation:
+               align buffers, data start, SG fragment length to avoid FMan DMA
+               splits.
+               FMAN DMA read or writes under heavy traffic load may cause FMAN
+               internal resource leak thus stopping further packet processing.
+               The FMAN internal queue can overflow when FMAN splits single
+               read or write transactions into multiple smaller transactions
+               such that more than 17 AXI transactions are in flight from FMAN
+               to interconnect. When the FMAN internal queue overflows, it can
+               stall further packet processing. The issue can occur with any
+               one of the following three conditions:
+               1. FMAN AXI transaction crosses 4K address boundary (Errata
+               A010022)
+               2. FMAN DMA address for an AXI transaction is not 16 byte
+               aligned, i.e. the last 4 bits of an address are non-zero
+               3. Scatter Gather (SG) frames have more than one SG buffer in
+               the SG list and any one of the buffers, except the last
+               buffer in the SG list has data size that is not a multiple
+               of 16 bytes, i.e., other than 16, 32, 48, 64, etc.
+               With any one of the above three conditions present, there is
+               likelihood of stalled FMAN packet processing, especially under
+               stress with multiple ports injecting line-rate traffic.
index 934111d..f151d6e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2020 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -566,6 +567,10 @@ struct fman_cfg {
        u32 qmi_def_tnums_thresh;
 };
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+static bool fman_has_err_a050385;
+#endif
+
 static irqreturn_t fman_exceptions(struct fman *fman,
                                   enum fman_exceptions exception)
 {
@@ -2518,6 +2523,14 @@ struct fman *fman_bind(struct device *fm_dev)
 }
 EXPORT_SYMBOL(fman_bind);
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+bool fman_has_errata_a050385(void)
+{
+       return fman_has_err_a050385;
+}
+EXPORT_SYMBOL(fman_has_errata_a050385);
+#endif
+
 static irqreturn_t fman_err_irq(int irq, void *handle)
 {
        struct fman *fman = (struct fman *)handle;
@@ -2845,6 +2858,11 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
                goto fman_free;
        }
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+       fman_has_err_a050385 =
+               of_property_read_bool(fm_node, "fsl,erratum-a050385");
+#endif
+
        return fman;
 
 fman_node_put:
index 935c317..f2ede13 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2020 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -398,6 +399,10 @@ u16 fman_get_max_frm(void);
 
 int fman_get_rx_extra_headroom(void);
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+bool fman_has_errata_a050385(void);
+#endif
+
 struct fman *fman_bind(struct device *dev);
 
 #endif /* __FM_H */
index 1b03139..d87158a 100644 (file)
@@ -46,6 +46,7 @@ enum HCLGE_MBX_OPCODE {
        HCLGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
        HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
        HCLGE_MBX_PUSH_PROMISC_INFO,    /* (PF -> VF) push vf promisc info */
+       HCLGE_MBX_VF_UNINIT,            /* (VF -> PF) vf is unintializing */
 
        HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf flr status */
        HCLGE_MBX_PUSH_LINK_STATUS,     /* (M7 -> PF) get port link status */
index acb796c..a7f40aa 100644 (file)
@@ -1711,7 +1711,7 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data)
        netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc);
 
        return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
-               kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
+               kinfo->dcb_ops->setup_tc(h, tc ? tc : 1, prio_tc) : -EOPNOTSUPP;
 }
 
 static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
index 492bc94..d3b0cd7 100644 (file)
@@ -2446,10 +2446,12 @@ static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
 
 int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
 {
+       struct hclge_mac *mac = &hdev->hw.mac;
        int ret;
 
        duplex = hclge_check_speed_dup(duplex, speed);
-       if (hdev->hw.mac.speed == speed && hdev->hw.mac.duplex == duplex)
+       if (!mac->support_autoneg && mac->speed == speed &&
+           mac->duplex == duplex)
                return 0;
 
        ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
@@ -7743,16 +7745,27 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type,
        struct hclge_desc desc;
        int ret;
 
-       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, false);
-
+       /* read current vlan filter parameter */
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, true);
        req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data;
        req->vlan_type = vlan_type;
-       req->vlan_fe = filter_en ? fe_type : 0;
        req->vf_id = vf_id;
 
        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "failed to get vlan filter config, ret = %d.\n", ret);
+               return ret;
+       }
+
+       /* modify and write new config parameter */
+       hclge_cmd_reuse_desc(&desc, false);
+       req->vlan_fe = filter_en ?
+                       (req->vlan_fe | fe_type) : (req->vlan_fe & ~fe_type);
+
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
        if (ret)
-               dev_err(&hdev->pdev->dev, "set vlan filter fail, ret =%d.\n",
+               dev_err(&hdev->pdev->dev, "failed to set vlan filter, ret = %d.\n",
                        ret);
 
        return ret;
@@ -8270,6 +8283,7 @@ void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
                        kfree(vlan);
                }
        }
+       clear_bit(vport->vport_id, hdev->vf_vlan_full);
 }
 
 void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
@@ -8486,6 +8500,28 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid,
        }
 }
 
+static void hclge_clear_vf_vlan(struct hclge_dev *hdev)
+{
+       struct hclge_vlan_info *vlan_info;
+       struct hclge_vport *vport;
+       int ret;
+       int vf;
+
+       /* clear port base vlan for all vf */
+       for (vf = HCLGE_VF_VPORT_START_NUM; vf < hdev->num_alloc_vport; vf++) {
+               vport = &hdev->vport[vf];
+               vlan_info = &vport->port_base_vlan_cfg.vlan_info;
+
+               ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
+                                              vport->vport_id,
+                                              vlan_info->vlan_tag, true);
+               if (ret)
+                       dev_err(&hdev->pdev->dev,
+                               "failed to clear vf vlan for vf%d, ret = %d\n",
+                               vf - HCLGE_VF_VPORT_START_NUM, ret);
+       }
+}
+
 int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
                          u16 vlan_id, bool is_kill)
 {
@@ -9895,6 +9931,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
        struct hclge_mac *mac = &hdev->hw.mac;
 
        hclge_reset_vf_rate(hdev);
+       hclge_clear_vf_vlan(hdev);
        hclge_misc_affinity_teardown(hdev);
        hclge_state_uninit(hdev);
 
index a3c0822..3d850f6 100644 (file)
@@ -799,6 +799,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
                        hclge_get_link_mode(vport, req);
                        break;
                case HCLGE_MBX_GET_VF_FLR_STATUS:
+               case HCLGE_MBX_VF_UNINIT:
                        hclge_rm_vport_all_mac_table(vport, true,
                                                     HCLGE_MAC_ADDR_UC);
                        hclge_rm_vport_all_mac_table(vport, true,
index d659720..0510d85 100644 (file)
@@ -2803,6 +2803,9 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
 {
        hclgevf_state_uninit(hdev);
 
+       hclgevf_send_mbx_msg(hdev, HCLGE_MBX_VF_UNINIT, 0, NULL, 0,
+                            false, NULL, 0);
+
        if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
                hclgevf_misc_irq_uninit(hdev);
                hclgevf_uninit_msi(hdev);
index 6f2cf56..79b3d53 100644 (file)
@@ -297,6 +297,7 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
        }
 
        hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
+       hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
 
        hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
        hw_ioctxt.cmdq_depth = 0;
index b069045..66fd234 100644 (file)
@@ -151,8 +151,8 @@ struct hinic_cmd_hw_ioctxt {
 
        u8      lro_en;
        u8      rsvd3;
+       u8      ppf_idx;
        u8      rsvd4;
-       u8      rsvd5;
 
        u16     rq_depth;
        u16     rx_buf_sz_idx;
index 5177945..c7bb9ce 100644 (file)
 #define HINIC_HWIF_FUNC_IDX(hwif)       ((hwif)->attr.func_idx)
 #define HINIC_HWIF_PCI_INTF(hwif)       ((hwif)->attr.pci_intf_idx)
 #define HINIC_HWIF_PF_IDX(hwif)         ((hwif)->attr.pf_idx)
+#define HINIC_HWIF_PPF_IDX(hwif)        ((hwif)->attr.ppf_idx)
 
 #define HINIC_FUNC_TYPE(hwif)           ((hwif)->attr.func_type)
 #define HINIC_IS_PF(hwif)               (HINIC_FUNC_TYPE(hwif) == HINIC_PF)
index f4a339b..79091e1 100644 (file)
@@ -94,6 +94,7 @@ struct hinic_rq {
 
        struct hinic_wq         *wq;
 
+       struct cpumask          affinity_mask;
        u32                     irq;
        u16                     msix_entry;
 
index 02a14f5..1356097 100644 (file)
@@ -356,7 +356,8 @@ static void hinic_enable_rss(struct hinic_dev *nic_dev)
        if (!num_cpus)
                num_cpus = num_online_cpus();
 
-       nic_dev->num_qps = min_t(u16, nic_dev->max_qps, num_cpus);
+       nic_dev->num_qps = hinic_hwdev_num_qps(hwdev);
+       nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus);
 
        nic_dev->rss_limit = nic_dev->num_qps;
        nic_dev->num_rss = nic_dev->num_qps;
index 56ea6d6..2695ad6 100644 (file)
@@ -475,7 +475,6 @@ static int rx_request_irq(struct hinic_rxq *rxq)
        struct hinic_hwdev *hwdev = nic_dev->hwdev;
        struct hinic_rq *rq = rxq->rq;
        struct hinic_qp *qp;
-       struct cpumask mask;
        int err;
 
        rx_add_napi(rxq);
@@ -492,8 +491,8 @@ static int rx_request_irq(struct hinic_rxq *rxq)
        }
 
        qp = container_of(rq, struct hinic_qp, rq);
-       cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask);
-       return irq_set_affinity_hint(rq->irq, &mask);
+       cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask);
+       return irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
 }
 
 static void rx_free_irq(struct hinic_rxq *rxq)
index c75239d..4bd3324 100644 (file)
@@ -2142,6 +2142,8 @@ static void __ibmvnic_reset(struct work_struct *work)
 {
        struct ibmvnic_rwi *rwi;
        struct ibmvnic_adapter *adapter;
+       bool saved_state = false;
+       unsigned long flags;
        u32 reset_state;
        int rc = 0;
 
@@ -2153,17 +2155,25 @@ static void __ibmvnic_reset(struct work_struct *work)
                return;
        }
 
-       reset_state = adapter->state;
-
        rwi = get_next_rwi(adapter);
        while (rwi) {
+               spin_lock_irqsave(&adapter->state_lock, flags);
+
                if (adapter->state == VNIC_REMOVING ||
                    adapter->state == VNIC_REMOVED) {
+                       spin_unlock_irqrestore(&adapter->state_lock, flags);
                        kfree(rwi);
                        rc = EBUSY;
                        break;
                }
 
+               if (!saved_state) {
+                       reset_state = adapter->state;
+                       adapter->state = VNIC_RESETTING;
+                       saved_state = true;
+               }
+               spin_unlock_irqrestore(&adapter->state_lock, flags);
+
                if (rwi->reset_reason == VNIC_RESET_CHANGE_PARAM) {
                        /* CHANGE_PARAM requestor holds rtnl_lock */
                        rc = do_change_param_reset(adapter, rwi, reset_state);
@@ -5091,6 +5101,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
                          __ibmvnic_delayed_reset);
        INIT_LIST_HEAD(&adapter->rwi_list);
        spin_lock_init(&adapter->rwi_lock);
+       spin_lock_init(&adapter->state_lock);
        mutex_init(&adapter->fw_lock);
        init_completion(&adapter->init_done);
        init_completion(&adapter->fw_done);
@@ -5163,8 +5174,17 @@ static int ibmvnic_remove(struct vio_dev *dev)
 {
        struct net_device *netdev = dev_get_drvdata(&dev->dev);
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->state_lock, flags);
+       if (adapter->state == VNIC_RESETTING) {
+               spin_unlock_irqrestore(&adapter->state_lock, flags);
+               return -EBUSY;
+       }
 
        adapter->state = VNIC_REMOVING;
+       spin_unlock_irqrestore(&adapter->state_lock, flags);
+
        rtnl_lock();
        unregister_netdevice(netdev);
 
index 60eccaf..f8416e1 100644 (file)
@@ -941,7 +941,8 @@ enum vnic_state {VNIC_PROBING = 1,
                 VNIC_CLOSING,
                 VNIC_CLOSED,
                 VNIC_REMOVING,
-                VNIC_REMOVED};
+                VNIC_REMOVED,
+                VNIC_RESETTING};
 
 enum ibmvnic_reset_reason {VNIC_RESET_FAILOVER = 1,
                           VNIC_RESET_MOBILITY,
@@ -1090,4 +1091,7 @@ struct ibmvnic_adapter {
 
        struct ibmvnic_tunables desired;
        struct ibmvnic_tunables fallback;
+
+       /* Used for serializatin of state field */
+       spinlock_t state_lock;
 };
index 0b9e851..d2e2dc5 100644 (file)
@@ -347,7 +347,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
        }
 
 
-       dev->err_interrupt = platform_get_irq(pdev, 0);
+       dev->err_interrupt = platform_get_irq_optional(pdev, 0);
        if (dev->err_interrupt > 0 &&
            resource_size(r) < MVMDIO_ERR_INT_MASK + 4) {
                dev_err(&pdev->dev,
@@ -364,8 +364,8 @@ static int orion_mdio_probe(struct platform_device *pdev)
                writel(MVMDIO_ERR_INT_SMI_DONE,
                        dev->regs + MVMDIO_ERR_INT_MASK);
 
-       } else if (dev->err_interrupt == -EPROBE_DEFER) {
-               ret = -EPROBE_DEFER;
+       } else if (dev->err_interrupt < 0) {
+               ret = dev->err_interrupt;
                goto out_mdio;
        }
 
index 9669836..21de476 100644 (file)
@@ -5147,7 +5147,6 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
-       struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
 
 #ifdef CONFIG_MLX5_CORE_EN_DCB
@@ -5168,7 +5167,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv)
                mlx5e_monitor_counter_cleanup(priv);
 
        mlx5e_disable_async_events(priv);
-       mlx5_lag_remove(mdev, netdev);
+       mlx5_lag_remove(mdev);
 }
 
 int mlx5e_update_nic_rx(struct mlx5e_priv *priv)
index 7b48cca..6ed307d 100644 (file)
@@ -1861,7 +1861,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 {
-       struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
 
@@ -1870,7 +1869,7 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 #endif
        mlx5_notifier_unregister(mdev, &priv->events_nb);
        cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
-       mlx5_lag_remove(mdev, netdev);
+       mlx5_lag_remove(mdev);
 }
 
 static MLX5E_DEFINE_STATS_GRP(sw_rep, 0);
index b91eabc..8e19f6a 100644 (file)
@@ -464,9 +464,6 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
        struct mlx5_lag *ldev;
        int changed = 0;
 
-       if (!net_eq(dev_net(ndev), &init_net))
-               return NOTIFY_DONE;
-
        if ((event != NETDEV_CHANGEUPPER) && (event != NETDEV_CHANGELOWERSTATE))
                return NOTIFY_DONE;
 
@@ -586,8 +583,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
 
        if (!ldev->nb.notifier_call) {
                ldev->nb.notifier_call = mlx5_lag_netdev_event;
-               if (register_netdevice_notifier_dev_net(netdev, &ldev->nb,
-                                                       &ldev->nn)) {
+               if (register_netdevice_notifier_net(&init_net, &ldev->nb)) {
                        ldev->nb.notifier_call = NULL;
                        mlx5_core_err(dev, "Failed to register LAG netdev notifier\n");
                }
@@ -600,7 +596,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
 }
 
 /* Must be called with intf_mutex held */
-void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev)
+void mlx5_lag_remove(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
        int i;
@@ -620,8 +616,7 @@ void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev)
 
        if (i == MLX5_MAX_PORTS) {
                if (ldev->nb.notifier_call)
-                       unregister_netdevice_notifier_dev_net(netdev, &ldev->nb,
-                                                             &ldev->nn);
+                       unregister_netdevice_notifier_net(&init_net, &ldev->nb);
                mlx5_lag_mp_cleanup(ldev);
                cancel_delayed_work_sync(&ldev->bond_work);
                mlx5_lag_dev_free(ldev);
index 316ab09..f1068aa 100644 (file)
@@ -44,7 +44,6 @@ struct mlx5_lag {
        struct workqueue_struct   *wq;
        struct delayed_work       bond_work;
        struct notifier_block     nb;
-       struct netdev_net_notifier      nn;
        struct lag_mp             lag_mp;
 };
 
index fcce9e0..da67b28 100644 (file)
@@ -157,7 +157,7 @@ int mlx5_query_qcam_reg(struct mlx5_core_dev *mdev, u32 *qcam,
                        u8 feature_group, u8 access_reg_group);
 
 void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev);
-void mlx5_lag_remove(struct mlx5_core_dev *dev, struct net_device *netdev);
+void mlx5_lag_remove(struct mlx5_core_dev *dev);
 
 int mlx5_irq_table_init(struct mlx5_core_dev *dev);
 void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev);
index e0d7d2d..43fa8c8 100644 (file)
@@ -28,7 +28,7 @@
 #define MLXSW_PCI_SW_RESET                     0xF0010
 #define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
 #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       900000
-#define MLXSW_PCI_SW_RESET_WAIT_MSECS          100
+#define MLXSW_PCI_SW_RESET_WAIT_MSECS          200
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
 #define MLXSW_PCI_FW_READY_MAGIC               0x5E
index 1c9e70c..58579ba 100644 (file)
@@ -513,14 +513,17 @@ static irqreturn_t ks_irq(int irq, void *pw)
 {
        struct net_device *netdev = pw;
        struct ks_net *ks = netdev_priv(netdev);
+       unsigned long flags;
        u16 status;
 
+       spin_lock_irqsave(&ks->statelock, flags);
        /*this should be the first in IRQ handler */
        ks_save_cmd_reg(ks);
 
        status = ks_rdreg16(ks, KS_ISR);
        if (unlikely(!status)) {
                ks_restore_cmd_reg(ks);
+               spin_unlock_irqrestore(&ks->statelock, flags);
                return IRQ_NONE;
        }
 
@@ -546,6 +549,7 @@ static irqreturn_t ks_irq(int irq, void *pw)
                ks->netdev->stats.rx_over_errors++;
        /* this should be the last in IRQ handler*/
        ks_restore_cmd_reg(ks);
+       spin_unlock_irqrestore(&ks->statelock, flags);
        return IRQ_HANDLED;
 }
 
@@ -615,6 +619,7 @@ static int ks_net_stop(struct net_device *netdev)
 
        /* shutdown RX/TX QMU */
        ks_disable_qmu(ks);
+       ks_disable_int(ks);
 
        /* set powermode to soft power down to save power */
        ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
@@ -671,10 +676,9 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        netdev_tx_t retv = NETDEV_TX_OK;
        struct ks_net *ks = netdev_priv(netdev);
+       unsigned long flags;
 
-       disable_irq(netdev->irq);
-       ks_disable_int(ks);
-       spin_lock(&ks->statelock);
+       spin_lock_irqsave(&ks->statelock, flags);
 
        /* Extra space are required:
        *  4 byte for alignment, 4 for status/length, 4 for CRC
@@ -688,9 +692,7 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                dev_kfree_skb(skb);
        } else
                retv = NETDEV_TX_BUSY;
-       spin_unlock(&ks->statelock);
-       ks_enable_int(ks);
-       enable_irq(netdev->irq);
+       spin_unlock_irqrestore(&ks->statelock, flags);
        return retv;
 }
 
index 86d543a..d3b7373 100644 (file)
@@ -2176,24 +2176,29 @@ static int ocelot_init_timestamp(struct ocelot *ocelot)
        return 0;
 }
 
-static void ocelot_port_set_mtu(struct ocelot *ocelot, int port, size_t mtu)
+/* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu.
+ * The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG.
+ */
+static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
+       int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
        int atop_wm;
 
-       ocelot_port_writel(ocelot_port, mtu, DEV_MAC_MAXLEN_CFG);
+       ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
 
        /* Set Pause WM hysteresis
-        * 152 = 6 * mtu / OCELOT_BUFFER_CELL_SZ
-        * 101 = 4 * mtu / OCELOT_BUFFER_CELL_SZ
+        * 152 = 6 * maxlen / OCELOT_BUFFER_CELL_SZ
+        * 101 = 4 * maxlen / OCELOT_BUFFER_CELL_SZ
         */
        ocelot_write_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA |
                         SYS_PAUSE_CFG_PAUSE_STOP(101) |
                         SYS_PAUSE_CFG_PAUSE_START(152), SYS_PAUSE_CFG, port);
 
        /* Tail dropping watermark */
-       atop_wm = (ocelot->shared_queue_sz - 9 * mtu) / OCELOT_BUFFER_CELL_SZ;
-       ocelot_write_rix(ocelot, ocelot_wm_enc(9 * mtu),
+       atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
+                  OCELOT_BUFFER_CELL_SZ;
+       ocelot_write_rix(ocelot, ocelot_wm_enc(9 * maxlen),
                         SYS_ATOP, port);
        ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
 }
@@ -2222,9 +2227,10 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
                           DEV_MAC_HDX_CFG);
 
        /* Set Max Length and maximum tags allowed */
-       ocelot_port_set_mtu(ocelot, port, VLAN_ETH_FRAME_LEN);
+       ocelot_port_set_maxlen(ocelot, port, ETH_DATA_LEN);
        ocelot_port_writel(ocelot_port, DEV_MAC_TAGS_CFG_TAG_ID(ETH_P_8021AD) |
                           DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
+                          DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA |
                           DEV_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA,
                           DEV_MAC_TAGS_CFG);
 
@@ -2310,18 +2316,18 @@ void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
         * Only one port can be an NPI at the same time.
         */
        if (cpu < ocelot->num_phys_ports) {
-               int mtu = VLAN_ETH_FRAME_LEN + OCELOT_TAG_LEN;
+               int sdu = ETH_DATA_LEN + OCELOT_TAG_LEN;
 
                ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
                             QSYS_EXT_CPU_CFG_EXT_CPU_PORT(cpu),
                             QSYS_EXT_CPU_CFG);
 
                if (injection == OCELOT_TAG_PREFIX_SHORT)
-                       mtu += OCELOT_SHORT_PREFIX_LEN;
+                       sdu += OCELOT_SHORT_PREFIX_LEN;
                else if (injection == OCELOT_TAG_PREFIX_LONG)
-                       mtu += OCELOT_LONG_PREFIX_LEN;
+                       sdu += OCELOT_LONG_PREFIX_LEN;
 
-               ocelot_port_set_mtu(ocelot, cpu, mtu);
+               ocelot_port_set_maxlen(ocelot, cpu, sdu);
        }
 
        /* CPU port Injection/Extraction configuration */
index 191271f..c2f5b69 100644 (file)
@@ -1688,7 +1688,7 @@ static int ionic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
        if (!(is_zero_ether_addr(mac) || is_valid_ether_addr(mac)))
                return -EINVAL;
 
-       down_read(&ionic->vf_op_lock);
+       down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
                ret = -EINVAL;
@@ -1698,7 +1698,7 @@ static int ionic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
                        ether_addr_copy(ionic->vfs[vf].macaddr, mac);
        }
 
-       up_read(&ionic->vf_op_lock);
+       up_write(&ionic->vf_op_lock);
        return ret;
 }
 
@@ -1719,7 +1719,7 @@ static int ionic_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
        if (proto != htons(ETH_P_8021Q))
                return -EPROTONOSUPPORT;
 
-       down_read(&ionic->vf_op_lock);
+       down_write(&ionic->vf_op_lock);
 
        if (vf >= pci_num_vf(ionic->pdev) || !ionic->vfs) {
                ret = -EINVAL;
@@ -1730,7 +1730,7 @@ static int ionic_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
                        ionic->vfs[vf].vlanid = vlan;
        }
 
-       up_read(&ionic->vf_op_lock);
+       up_write(&ionic->vf_op_lock);
        return ret;
 }
 
index 06de595..fbf4cbc 100644 (file)
 #include "rmnet_vnd.h"
 #include "rmnet_private.h"
 
-/* Locking scheme -
- * The shared resource which needs to be protected is realdev->rx_handler_data.
- * For the writer path, this is using rtnl_lock(). The writer paths are
- * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These
- * paths are already called with rtnl_lock() acquired in. There is also an
- * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For
- * dereference here, we will need to use rtnl_dereference(). Dev list writing
- * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link().
- * For the reader path, the real_dev->rx_handler_data is called in the TX / RX
- * path. We only need rcu_read_lock() for these scenarios. In these cases,
- * the rcu_read_lock() is held in __dev_queue_xmit() and
- * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl()
- * to get the relevant information. For dev list reading, we again acquire
- * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu().
- * We also use unregister_netdevice_many() to free all rmnet devices in
- * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in
- * same context.
- */
-
 /* Local Definitions and Declarations */
 
 static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = {
@@ -51,9 +32,10 @@ rmnet_get_port_rtnl(const struct net_device *real_dev)
        return rtnl_dereference(real_dev->rx_handler_data);
 }
 
-static int rmnet_unregister_real_device(struct net_device *real_dev,
-                                       struct rmnet_port *port)
+static int rmnet_unregister_real_device(struct net_device *real_dev)
 {
+       struct rmnet_port *port = rmnet_get_port_rtnl(real_dev);
+
        if (port->nr_rmnet_devs)
                return -EINVAL;
 
@@ -61,9 +43,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev,
 
        kfree(port);
 
-       /* release reference on real_dev */
-       dev_put(real_dev);
-
        netdev_dbg(real_dev, "Removed from rmnet\n");
        return 0;
 }
@@ -89,9 +68,6 @@ static int rmnet_register_real_device(struct net_device *real_dev)
                return -EBUSY;
        }
 
-       /* hold on to real dev for MAP data */
-       dev_hold(real_dev);
-
        for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
                INIT_HLIST_HEAD(&port->muxed_ep[entry]);
 
@@ -99,28 +75,33 @@ static int rmnet_register_real_device(struct net_device *real_dev)
        return 0;
 }
 
-static void rmnet_unregister_bridge(struct net_device *dev,
-                                   struct rmnet_port *port)
+static void rmnet_unregister_bridge(struct rmnet_port *port)
 {
-       struct rmnet_port *bridge_port;
-       struct net_device *bridge_dev;
+       struct net_device *bridge_dev, *real_dev, *rmnet_dev;
+       struct rmnet_port *real_port;
 
        if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
                return;
 
-       /* bridge slave handling */
+       rmnet_dev = port->rmnet_dev;
        if (!port->nr_rmnet_devs) {
-               bridge_dev = port->bridge_ep;
+               /* bridge device */
+               real_dev = port->bridge_ep;
+               bridge_dev = port->dev;
 
-               bridge_port = rmnet_get_port_rtnl(bridge_dev);
-               bridge_port->bridge_ep = NULL;
-               bridge_port->rmnet_mode = RMNET_EPMODE_VND;
+               real_port = rmnet_get_port_rtnl(real_dev);
+               real_port->bridge_ep = NULL;
+               real_port->rmnet_mode = RMNET_EPMODE_VND;
        } else {
+               /* real device */
                bridge_dev = port->bridge_ep;
 
-               bridge_port = rmnet_get_port_rtnl(bridge_dev);
-               rmnet_unregister_real_device(bridge_dev, bridge_port);
+               port->bridge_ep = NULL;
+               port->rmnet_mode = RMNET_EPMODE_VND;
        }
+
+       netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
+       rmnet_unregister_real_device(bridge_dev);
 }
 
 static int rmnet_newlink(struct net *src_net, struct net_device *dev,
@@ -135,6 +116,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
        int err = 0;
        u16 mux_id;
 
+       if (!tb[IFLA_LINK]) {
+               NL_SET_ERR_MSG_MOD(extack, "link not specified");
+               return -EINVAL;
+       }
+
        real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
        if (!real_dev || !dev)
                return -ENODEV;
@@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
        if (err)
                goto err1;
 
+       err = netdev_upper_dev_link(real_dev, dev, extack);
+       if (err < 0)
+               goto err2;
+
        port->rmnet_mode = mode;
+       port->rmnet_dev = dev;
 
        hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
 
@@ -173,8 +164,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
 
        return 0;
 
+err2:
+       unregister_netdevice(dev);
+       rmnet_vnd_dellink(mux_id, port, ep);
 err1:
-       rmnet_unregister_real_device(real_dev, port);
+       rmnet_unregister_real_device(real_dev);
 err0:
        kfree(ep);
        return err;
@@ -183,77 +177,74 @@ err0:
 static void rmnet_dellink(struct net_device *dev, struct list_head *head)
 {
        struct rmnet_priv *priv = netdev_priv(dev);
-       struct net_device *real_dev;
+       struct net_device *real_dev, *bridge_dev;
+       struct rmnet_port *real_port, *bridge_port;
        struct rmnet_endpoint *ep;
-       struct rmnet_port *port;
-       u8 mux_id;
+       u8 mux_id = priv->mux_id;
 
        real_dev = priv->real_dev;
 
-       if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+       if (!rmnet_is_real_dev_registered(real_dev))
                return;
 
-       port = rmnet_get_port_rtnl(real_dev);
-
-       mux_id = rmnet_vnd_get_mux(dev);
+       real_port = rmnet_get_port_rtnl(real_dev);
+       bridge_dev = real_port->bridge_ep;
+       if (bridge_dev) {
+               bridge_port = rmnet_get_port_rtnl(bridge_dev);
+               rmnet_unregister_bridge(bridge_port);
+       }
 
-       ep = rmnet_get_endpoint(port, mux_id);
+       ep = rmnet_get_endpoint(real_port, mux_id);
        if (ep) {
                hlist_del_init_rcu(&ep->hlnode);
-               rmnet_unregister_bridge(dev, port);
-               rmnet_vnd_dellink(mux_id, port, ep);
+               rmnet_vnd_dellink(mux_id, real_port, ep);
                kfree(ep);
        }
-       rmnet_unregister_real_device(real_dev, port);
 
+       netdev_upper_dev_unlink(real_dev, dev);
+       rmnet_unregister_real_device(real_dev);
        unregister_netdevice_queue(dev, head);
 }
 
-static void rmnet_force_unassociate_device(struct net_device *dev)
+static void rmnet_force_unassociate_device(struct net_device *real_dev)
 {
-       struct net_device *real_dev = dev;
        struct hlist_node *tmp_ep;
        struct rmnet_endpoint *ep;
        struct rmnet_port *port;
        unsigned long bkt_ep;
        LIST_HEAD(list);
 
-       if (!rmnet_is_real_dev_registered(real_dev))
-               return;
-
-       ASSERT_RTNL();
-
-       port = rmnet_get_port_rtnl(dev);
-
-       rcu_read_lock();
-       rmnet_unregister_bridge(dev, port);
-
-       hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
-               unregister_netdevice_queue(ep->egress_dev, &list);
-               rmnet_vnd_dellink(ep->mux_id, port, ep);
+       port = rmnet_get_port_rtnl(real_dev);
 
-               hlist_del_init_rcu(&ep->hlnode);
-               kfree(ep);
+       if (port->nr_rmnet_devs) {
+               /* real device */
+               rmnet_unregister_bridge(port);
+               hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
+                       unregister_netdevice_queue(ep->egress_dev, &list);
+                       netdev_upper_dev_unlink(real_dev, ep->egress_dev);
+                       rmnet_vnd_dellink(ep->mux_id, port, ep);
+                       hlist_del_init_rcu(&ep->hlnode);
+                       kfree(ep);
+               }
+               rmnet_unregister_real_device(real_dev);
+               unregister_netdevice_many(&list);
+       } else {
+               rmnet_unregister_bridge(port);
        }
-
-       rcu_read_unlock();
-       unregister_netdevice_many(&list);
-
-       rmnet_unregister_real_device(real_dev, port);
 }
 
 static int rmnet_config_notify_cb(struct notifier_block *nb,
                                  unsigned long event, void *data)
 {
-       struct net_device *dev = netdev_notifier_info_to_dev(data);
+       struct net_device *real_dev = netdev_notifier_info_to_dev(data);
 
-       if (!dev)
+       if (!rmnet_is_real_dev_registered(real_dev))
                return NOTIFY_DONE;
 
        switch (event) {
        case NETDEV_UNREGISTER:
-               netdev_dbg(dev, "Kernel unregister\n");
-               rmnet_force_unassociate_device(dev);
+               netdev_dbg(real_dev, "Kernel unregister\n");
+               rmnet_force_unassociate_device(real_dev);
                break;
 
        default:
@@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
        if (!dev)
                return -ENODEV;
 
-       real_dev = __dev_get_by_index(dev_net(dev),
-                                     nla_get_u32(tb[IFLA_LINK]));
-
-       if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+       real_dev = priv->real_dev;
+       if (!rmnet_is_real_dev_registered(real_dev))
                return -ENODEV;
 
        port = rmnet_get_port_rtnl(real_dev);
 
        if (data[IFLA_RMNET_MUX_ID]) {
                mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
+               if (rmnet_get_endpoint(port, mux_id)) {
+                       NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists");
+                       return -EINVAL;
+               }
                ep = rmnet_get_endpoint(port, priv->mux_id);
                if (!ep)
                        return -ENODEV;
@@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = {
        .fill_info      = rmnet_fill_info,
 };
 
-/* Needs either rcu_read_lock() or rtnl lock */
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev)
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev)
 {
        if (rmnet_is_real_dev_registered(real_dev))
-               return rcu_dereference_rtnl(real_dev->rx_handler_data);
+               return rcu_dereference_bh(real_dev->rx_handler_data);
        else
                return NULL;
 }
@@ -409,7 +401,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        struct rmnet_port *port, *slave_port;
        int err;
 
-       port = rmnet_get_port(real_dev);
+       port = rmnet_get_port_rtnl(real_dev);
 
        /* If there is more than one rmnet dev attached, its probably being
         * used for muxing. Skip the briding in that case
@@ -417,6 +409,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        if (port->nr_rmnet_devs > 1)
                return -EINVAL;
 
+       if (port->rmnet_mode != RMNET_EPMODE_VND)
+               return -EINVAL;
+
        if (rmnet_is_real_dev_registered(slave_dev))
                return -EBUSY;
 
@@ -424,9 +419,17 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
        if (err)
                return -EBUSY;
 
-       slave_port = rmnet_get_port(slave_dev);
+       err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
+                                          extack);
+       if (err) {
+               rmnet_unregister_real_device(slave_dev);
+               return err;
+       }
+
+       slave_port = rmnet_get_port_rtnl(slave_dev);
        slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
        slave_port->bridge_ep = real_dev;
+       slave_port->rmnet_dev = rmnet_dev;
 
        port->rmnet_mode = RMNET_EPMODE_BRIDGE;
        port->bridge_ep = slave_dev;
@@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
 int rmnet_del_bridge(struct net_device *rmnet_dev,
                     struct net_device *slave_dev)
 {
-       struct rmnet_priv *priv = netdev_priv(rmnet_dev);
-       struct net_device *real_dev = priv->real_dev;
-       struct rmnet_port *port, *slave_port;
+       struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
 
-       port = rmnet_get_port(real_dev);
-       port->rmnet_mode = RMNET_EPMODE_VND;
-       port->bridge_ep = NULL;
-
-       slave_port = rmnet_get_port(slave_dev);
-       rmnet_unregister_real_device(slave_dev, slave_port);
+       rmnet_unregister_bridge(port);
 
        netdev_dbg(slave_dev, "removed from rmnet as slave\n");
        return 0;
@@ -473,8 +469,8 @@ static int __init rmnet_init(void)
 
 static void __exit rmnet_exit(void)
 {
-       unregister_netdevice_notifier(&rmnet_dev_notifier);
        rtnl_link_unregister(&rmnet_link_ops);
+       unregister_netdevice_notifier(&rmnet_dev_notifier);
 }
 
 module_init(rmnet_init)
index cd0a6bc..be51598 100644 (file)
@@ -28,6 +28,7 @@ struct rmnet_port {
        u8 rmnet_mode;
        struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
        struct net_device *bridge_ep;
+       struct net_device *rmnet_dev;
 };
 
 extern struct rtnl_link_ops rmnet_link_ops;
@@ -65,7 +66,7 @@ struct rmnet_priv {
        struct rmnet_priv_stats stats;
 };
 
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev);
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev);
 struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id);
 int rmnet_add_bridge(struct net_device *rmnet_dev,
                     struct net_device *slave_dev,
index 1b74bc1..29a7bfa 100644 (file)
@@ -159,6 +159,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb,
 static void
 rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev)
 {
+       if (skb_mac_header_was_set(skb))
+               skb_push(skb, skb->mac_len);
+
        if (bridge_dev) {
                skb->dev = bridge_dev;
                dev_queue_xmit(skb);
@@ -184,7 +187,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb)
                return RX_HANDLER_PASS;
 
        dev = skb->dev;
-       port = rmnet_get_port(dev);
+       port = rmnet_get_port_rcu(dev);
 
        switch (port->rmnet_mode) {
        case RMNET_EPMODE_VND:
@@ -217,7 +220,7 @@ void rmnet_egress_handler(struct sk_buff *skb)
        skb->dev = priv->real_dev;
        mux_id = priv->mux_id;
 
-       port = rmnet_get_port(skb->dev);
+       port = rmnet_get_port_rcu(skb->dev);
        if (!port)
                goto drop;
 
index 509dfc8..26ad40f 100644 (file)
@@ -266,14 +266,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
        return 0;
 }
 
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev)
-{
-       struct rmnet_priv *priv;
-
-       priv = netdev_priv(rmnet_dev);
-       return priv->mux_id;
-}
-
 int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
 {
        netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
index 54cbaf3..14d77c7 100644 (file)
@@ -16,6 +16,5 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port,
                      struct rmnet_endpoint *ep);
 void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev);
 void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev);
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev);
 void rmnet_vnd_setup(struct net_device *dev);
 #endif /* _RMNET_VND_H_ */
index c705743..2cc8184 100644 (file)
@@ -2277,7 +2277,7 @@ static int __init sxgbe_cmdline_opt(char *str)
        if (!str || !*str)
                return -EINVAL;
        while ((opt = strsep(&str, ",")) != NULL) {
-               if (!strncmp(opt, "eee_timer:", 6)) {
+               if (!strncmp(opt, "eee_timer:", 10)) {
                        if (kstrtoint(opt + 10, 0, &eee_timer))
                                goto err;
                }
index 52113b7..3f16bd8 100644 (file)
@@ -2853,11 +2853,24 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
        }
 
        /* Transmit timestamps are only available for 8XXX series. They result
-        * in three events per packet. These occur in order, and are:
-        *  - the normal completion event
+        * in up to three events per packet. These occur in order, and are:
+        *  - the normal completion event (may be omitted)
         *  - the low part of the timestamp
         *  - the high part of the timestamp
         *
+        * It's possible for multiple completion events to appear before the
+        * corresponding timestamps. So we can for example get:
+        *  COMP N
+        *  COMP N+1
+        *  TS_LO N
+        *  TS_HI N
+        *  TS_LO N+1
+        *  TS_HI N+1
+        *
+        * In addition it's also possible for the adjacent completions to be
+        * merged, so we may not see COMP N above. As such, the completion
+        * events are not very useful here.
+        *
         * Each part of the timestamp is itself split across two 16 bit
         * fields in the event.
         */
@@ -2865,17 +2878,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
 
        switch (tx_ev_type) {
        case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
-               /* In case of Queue flush or FLR, we might have received
-                * the previous TX completion event but not the Timestamp
-                * events.
-                */
-               if (tx_queue->completed_desc_ptr != tx_queue->ptr_mask)
-                       efx_xmit_done(tx_queue, tx_queue->completed_desc_ptr);
-
-               tx_ev_desc_ptr = EFX_QWORD_FIELD(*event,
-                                                ESF_DZ_TX_DESCR_INDX);
-               tx_queue->completed_desc_ptr =
-                                       tx_ev_desc_ptr & tx_queue->ptr_mask;
+               /* Ignore this event - see above. */
                break;
 
        case TX_TIMESTAMP_EVENT_TX_EV_TSTAMP_LO:
@@ -2887,8 +2890,7 @@ efx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
                ts_part = efx_ef10_extract_event_ts(event);
                tx_queue->completed_timestamp_major = ts_part;
 
-               efx_xmit_done(tx_queue, tx_queue->completed_desc_ptr);
-               tx_queue->completed_desc_ptr = tx_queue->ptr_mask;
+               efx_xmit_done_single(tx_queue);
                break;
 
        default:
index f1bdb04..95395d6 100644 (file)
@@ -20,6 +20,7 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
                                struct net_device *net_dev);
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+void efx_xmit_done_single(struct efx_tx_queue *tx_queue);
 int efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type,
                 void *type_data);
 extern unsigned int efx_piobuf_size;
index aeb5e8a..73d4e39 100644 (file)
@@ -583,6 +583,7 @@ struct efx_channel *efx_copy_channel(const struct efx_channel *old_channel)
                if (tx_queue->channel)
                        tx_queue->channel = channel;
                tx_queue->buffer = NULL;
+               tx_queue->cb_page = NULL;
                memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
        }
 
index 9f9886f..8164f0e 100644 (file)
@@ -208,8 +208,6 @@ struct efx_tx_buffer {
  *     avoid cache-line ping-pong between the xmit path and the
  *     completion path.
  * @merge_events: Number of TX merged completion events
- * @completed_desc_ptr: Most recent completed pointer - only used with
- *      timestamping.
  * @completed_timestamp_major: Top part of the most recent tx timestamp.
  * @completed_timestamp_minor: Low part of the most recent tx timestamp.
  * @insert_count: Current insert pointer
@@ -269,7 +267,6 @@ struct efx_tx_queue {
        unsigned int merge_events;
        unsigned int bytes_compl;
        unsigned int pkts_compl;
-       unsigned int completed_desc_ptr;
        u32 completed_timestamp_major;
        u32 completed_timestamp_minor;
 
index af15a73..59b4f16 100644 (file)
@@ -560,13 +560,45 @@ efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx,
                                    u32 nic_major, u32 nic_minor,
                                    s32 correction)
 {
+       u32 sync_timestamp;
        ktime_t kt = { 0 };
+       s16 delta;
 
        if (!(nic_major & 0x80000000)) {
                WARN_ON_ONCE(nic_major >> 16);
-               /* Use the top bits from the latest sync event. */
-               nic_major &= 0xffff;
-               nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000);
+
+               /* Medford provides 48 bits of timestamp, so we must get the top
+                * 16 bits from the timesync event state.
+                *
+                * We only have the lower 16 bits of the time now, but we do
+                * have a full resolution timestamp at some point in past. As
+                * long as the difference between the (real) now and the sync
+                * is less than 2^15, then we can reconstruct the difference
+                * between those two numbers using only the lower 16 bits of
+                * each.
+                *
+                * Put another way
+                *
+                * a - b = ((a mod k) - b) mod k
+                *
+                * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know
+                * (a mod k) and b, so can calculate the delta, a - b.
+                *
+                */
+               sync_timestamp = last_sync_timestamp_major(efx);
+
+               /* Because delta is s16 this does an implicit mask down to
+                * 16 bits which is what we need, assuming
+                * MEDFORD_TX_SECS_EVENT_BITS is 16. delta is signed so that
+                * we can deal with the (unlikely) case of sync timestamps
+                * arriving from the future.
+                */
+               delta = nic_major - sync_timestamp;
+
+               /* Recover the fully specified time now, by applying the offset
+                * to the (fully specified) sync time.
+                */
+               nic_major = sync_timestamp + delta;
 
                kt = ptp->nic_to_kernel_time(nic_major, nic_minor,
                                             correction);
index 04d7f41..8aafc54 100644 (file)
@@ -535,6 +535,44 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
        return efx_enqueue_skb(tx_queue, skb);
 }
 
+void efx_xmit_done_single(struct efx_tx_queue *tx_queue)
+{
+       unsigned int pkts_compl = 0, bytes_compl = 0;
+       unsigned int read_ptr;
+       bool finished = false;
+
+       read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
+
+       while (!finished) {
+               struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
+
+               if (!efx_tx_buffer_in_use(buffer)) {
+                       struct efx_nic *efx = tx_queue->efx;
+
+                       netif_err(efx, hw, efx->net_dev,
+                                 "TX queue %d spurious single TX completion\n",
+                                 tx_queue->queue);
+                       efx_schedule_reset(efx, RESET_TYPE_TX_SKIP);
+                       return;
+               }
+
+               /* Need to check the flag before dequeueing. */
+               if (buffer->flags & EFX_TX_BUF_SKB)
+                       finished = true;
+               efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
+
+               ++tx_queue->read_count;
+               read_ptr = tx_queue->read_count & tx_queue->ptr_mask;
+       }
+
+       tx_queue->pkts_compl += pkts_compl;
+       tx_queue->bytes_compl += bytes_compl;
+
+       EFX_WARN_ON_PARANOID(pkts_compl != 1);
+
+       efx_xmit_done_check_empty(tx_queue);
+}
+
 void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
 {
        struct efx_nic *efx = tx_queue->efx;
index b1571e9..70876df 100644 (file)
@@ -80,7 +80,6 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
        tx_queue->xmit_more_available = false;
        tx_queue->timestamping = (efx_ptp_use_mac_tx_timestamps(efx) &&
                                  tx_queue->channel == efx_ptp_channel(efx));
-       tx_queue->completed_desc_ptr = tx_queue->ptr_mask;
        tx_queue->completed_timestamp_major = 0;
        tx_queue->completed_timestamp_minor = 0;
 
@@ -210,10 +209,9 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
        while (read_ptr != stop_index) {
                struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
 
-               if (!(buffer->flags & EFX_TX_BUF_OPTION) &&
-                   unlikely(buffer->len == 0)) {
+               if (!efx_tx_buffer_in_use(buffer)) {
                        netif_err(efx, tx_err, efx->net_dev,
-                                 "TX queue %d spurious TX completion id %x\n",
+                                 "TX queue %d spurious TX completion id %d\n",
                                  tx_queue->queue, read_ptr);
                        efx_schedule_reset(efx, RESET_TYPE_TX_SKIP);
                        return;
@@ -226,6 +224,19 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
        }
 }
 
+void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue)
+{
+       if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
+               tx_queue->old_write_count = READ_ONCE(tx_queue->write_count);
+               if (tx_queue->read_count == tx_queue->old_write_count) {
+                       /* Ensure that read_count is flushed. */
+                       smp_mb();
+                       tx_queue->empty_read_count =
+                               tx_queue->read_count | EFX_EMPTY_COUNT_VALID;
+               }
+       }
+}
+
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
 {
        unsigned int fill_level, pkts_compl = 0, bytes_compl = 0;
@@ -256,15 +267,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
                        netif_tx_wake_queue(tx_queue->core_txq);
        }
 
-       /* Check whether the hardware queue is now empty */
-       if ((int)(tx_queue->read_count - tx_queue->old_write_count) >= 0) {
-               tx_queue->old_write_count = READ_ONCE(tx_queue->write_count);
-               if (tx_queue->read_count == tx_queue->old_write_count) {
-                       smp_mb();
-                       tx_queue->empty_read_count =
-                               tx_queue->read_count | EFX_EMPTY_COUNT_VALID;
-               }
-       }
+       efx_xmit_done_check_empty(tx_queue);
 }
 
 /* Remove buffers put into a tx_queue for the current packet.
index f92f1fe..99cf7ce 100644 (file)
@@ -21,6 +21,12 @@ void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
                        unsigned int *pkts_compl,
                        unsigned int *bytes_compl);
 
+static inline bool efx_tx_buffer_in_use(struct efx_tx_buffer *buffer)
+{
+       return buffer->len || (buffer->flags & EFX_TX_BUF_OPTION);
+}
+
+void efx_xmit_done_check_empty(struct efx_tx_queue *tx_queue);
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
 
 void efx_enqueue_unwind(struct efx_tx_queue *tx_queue,
index d0356fb..5427843 100644 (file)
@@ -24,6 +24,7 @@
 static void dwmac1000_core_init(struct mac_device_info *hw,
                                struct net_device *dev)
 {
+       struct stmmac_priv *priv = netdev_priv(dev);
        void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONTROL);
        int mtu = dev->mtu;
@@ -35,7 +36,7 @@ static void dwmac1000_core_init(struct mac_device_info *hw,
         * Broadcom tags can look like invalid LLC/SNAP packets and cause the
         * hardware to truncate packets on reception.
         */
-       if (netdev_uses_dsa(dev))
+       if (netdev_uses_dsa(dev) || !priv->plat->enh_desc)
                value &= ~GMAC_CONTROL_ACS;
 
        if (mtu > 1500)
index 5836b21..7da18c9 100644 (file)
@@ -4405,6 +4405,8 @@ static void stmmac_init_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
+       rtnl_lock();
+
        /* Create per netdev entries */
        priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
 
@@ -4416,14 +4418,13 @@ static void stmmac_init_fs(struct net_device *dev)
        debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev,
                            &stmmac_dma_cap_fops);
 
-       register_netdevice_notifier(&stmmac_notifier);
+       rtnl_unlock();
 }
 
 static void stmmac_exit_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(priv->dbgfs_dir);
 }
 #endif /* CONFIG_DEBUG_FS */
@@ -4940,14 +4941,14 @@ int stmmac_dvr_remove(struct device *dev)
 
        netdev_info(priv->dev, "%s: removing driver", __func__);
 
-#ifdef CONFIG_DEBUG_FS
-       stmmac_exit_fs(ndev);
-#endif
        stmmac_stop_all_dma(priv);
 
        stmmac_mac_set(priv, priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
+#ifdef CONFIG_DEBUG_FS
+       stmmac_exit_fs(ndev);
+#endif
        phylink_destroy(priv->phylink);
        if (priv->plat->stmmac_rst)
                reset_control_assert(priv->plat->stmmac_rst);
@@ -5166,6 +5167,7 @@ static int __init stmmac_init(void)
        /* Create debugfs main directory if it doesn't exist yet */
        if (!stmmac_fs_dir)
                stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
+       register_netdevice_notifier(&stmmac_notifier);
 #endif
 
        return 0;
@@ -5174,6 +5176,7 @@ static int __init stmmac_init(void)
 static void __exit stmmac_exit(void)
 {
 #ifdef CONFIG_DEBUG_FS
+       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(stmmac_fs_dir);
 #endif
 }
index 276292b..53fb814 100644 (file)
@@ -375,10 +375,14 @@ struct temac_local {
        int tx_bd_next;
        int tx_bd_tail;
        int rx_bd_ci;
+       int rx_bd_tail;
 
        /* DMA channel control setup */
        u32 tx_chnl_ctrl;
        u32 rx_chnl_ctrl;
+       u8 coalesce_count_rx;
+
+       struct delayed_work restart_work;
 };
 
 /* Wrappers for temac_ior()/temac_iow() function pointers above */
index 6f11f52..9461ace 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/ip.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <linux/processor.h>
 #include <linux/platform_data/xilinx-ll-temac.h>
@@ -367,6 +368,8 @@ static int temac_dma_bd_init(struct net_device *ndev)
                skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                              XTE_MAX_JUMBO_FRAME_SIZE,
                                              DMA_FROM_DEVICE);
+               if (dma_mapping_error(ndev->dev.parent, skb_dma_addr))
+                       goto out;
                lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr);
                lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
                lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
@@ -387,12 +390,13 @@ static int temac_dma_bd_init(struct net_device *ndev)
        lp->tx_bd_next = 0;
        lp->tx_bd_tail = 0;
        lp->rx_bd_ci = 0;
+       lp->rx_bd_tail = RX_BD_NUM - 1;
 
        /* Enable RX DMA transfers */
        wmb();
        lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
        lp->dma_out(lp, RX_TAILDESC_PTR,
-                      lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+                      lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail));
 
        /* Prepare for TX DMA transfer */
        lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
@@ -788,6 +792,9 @@ static void temac_start_xmit_done(struct net_device *ndev)
                stat = be32_to_cpu(cur_p->app0);
        }
 
+       /* Matches barrier in temac_start_xmit */
+       smp_mb();
+
        netif_wake_queue(ndev);
 }
 
@@ -830,9 +837,19 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 
        if (temac_check_tx_bd_space(lp, num_frag + 1)) {
-               if (!netif_queue_stopped(ndev))
-                       netif_stop_queue(ndev);
-               return NETDEV_TX_BUSY;
+               if (netif_queue_stopped(ndev))
+                       return NETDEV_TX_BUSY;
+
+               netif_stop_queue(ndev);
+
+               /* Matches barrier in temac_start_xmit_done */
+               smp_mb();
+
+               /* Space might have just been freed - check again */
+               if (temac_check_tx_bd_space(lp, num_frag))
+                       return NETDEV_TX_BUSY;
+
+               netif_wake_queue(ndev);
        }
 
        cur_p->app0 = 0;
@@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                      skb_headlen(skb), DMA_TO_DEVICE);
        cur_p->len = cpu_to_be32(skb_headlen(skb));
+       if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) {
+               dev_kfree_skb_any(skb);
+               ndev->stats.tx_dropped++;
+               return NETDEV_TX_OK;
+       }
        cur_p->phys = cpu_to_be32(skb_dma_addr);
        ptr_to_txbd((void *)skb, cur_p);
 
        for (ii = 0; ii < num_frag; ii++) {
-               lp->tx_bd_tail++;
-               if (lp->tx_bd_tail >= TX_BD_NUM)
+               if (++lp->tx_bd_tail >= TX_BD_NUM)
                        lp->tx_bd_tail = 0;
 
                cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
@@ -863,6 +884,27 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                              skb_frag_address(frag),
                                              skb_frag_size(frag),
                                              DMA_TO_DEVICE);
+               if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) {
+                       if (--lp->tx_bd_tail < 0)
+                               lp->tx_bd_tail = TX_BD_NUM - 1;
+                       cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+                       while (--ii >= 0) {
+                               --frag;
+                               dma_unmap_single(ndev->dev.parent,
+                                                be32_to_cpu(cur_p->phys),
+                                                skb_frag_size(frag),
+                                                DMA_TO_DEVICE);
+                               if (--lp->tx_bd_tail < 0)
+                                       lp->tx_bd_tail = TX_BD_NUM - 1;
+                               cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+                       }
+                       dma_unmap_single(ndev->dev.parent,
+                                        be32_to_cpu(cur_p->phys),
+                                        skb_headlen(skb), DMA_TO_DEVICE);
+                       dev_kfree_skb_any(skb);
+                       ndev->stats.tx_dropped++;
+                       return NETDEV_TX_OK;
+               }
                cur_p->phys = cpu_to_be32(skb_dma_addr);
                cur_p->len = cpu_to_be32(skb_frag_size(frag));
                cur_p->app0 = 0;
@@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+static int ll_temac_recv_buffers_available(struct temac_local *lp)
+{
+       int available;
+
+       if (!lp->rx_skb[lp->rx_bd_ci])
+               return 0;
+       available = 1 + lp->rx_bd_tail - lp->rx_bd_ci;
+       if (available <= 0)
+               available += RX_BD_NUM;
+       return available;
+}
 
 static void ll_temac_recv(struct net_device *ndev)
 {
        struct temac_local *lp = netdev_priv(ndev);
-       struct sk_buff *skb, *new_skb;
-       unsigned int bdstat;
-       struct cdmac_bd *cur_p;
-       dma_addr_t tail_p, skb_dma_addr;
-       int length;
        unsigned long flags;
+       int rx_bd;
+       bool update_tail = false;
 
        spin_lock_irqsave(&lp->rx_lock, flags);
 
-       tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
-       cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-
-       bdstat = be32_to_cpu(cur_p->app0);
-       while ((bdstat & STS_CTRL_APP0_CMPLT)) {
+       /* Process all received buffers, passing them on network
+        * stack.  After this, the buffer descriptors will be in an
+        * un-allocated stage, where no skb is allocated for it, and
+        * they are therefore not available for TEMAC/DMA.
+        */
+       do {
+               struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci];
+               struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci];
+               unsigned int bdstat = be32_to_cpu(bd->app0);
+               int length;
+
+               /* While this should not normally happen, we can end
+                * here when GFP_ATOMIC allocations fail, and we
+                * therefore have un-allocated buffers.
+                */
+               if (!skb)
+                       break;
 
-               skb = lp->rx_skb[lp->rx_bd_ci];
-               length = be32_to_cpu(cur_p->app4) & 0x3FFF;
+               /* Loop over all completed buffer descriptors */
+               if (!(bdstat & STS_CTRL_APP0_CMPLT))
+                       break;
 
-               dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys),
+               dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys),
                                 XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
+               /* The buffer is not valid for DMA anymore */
+               bd->phys = 0;
+               bd->len = 0;
 
+               length = be32_to_cpu(bd->app4) & 0x3FFF;
                skb_put(skb, length);
                skb->protocol = eth_type_trans(skb, ndev);
                skb_checksum_none_assert(skb);
@@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev)
                         * (back) for proper IP checksum byte order
                         * (be16).
                         */
-                       skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF);
+                       skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF);
                        skb->ip_summed = CHECKSUM_COMPLETE;
                }
 
                if (!skb_defer_rx_timestamp(skb))
                        netif_rx(skb);
+               /* The skb buffer is now owned by network stack above */
+               lp->rx_skb[lp->rx_bd_ci] = NULL;
 
                ndev->stats.rx_packets++;
                ndev->stats.rx_bytes += length;
 
-               new_skb = netdev_alloc_skb_ip_align(ndev,
-                                               XTE_MAX_JUMBO_FRAME_SIZE);
-               if (!new_skb) {
-                       spin_unlock_irqrestore(&lp->rx_lock, flags);
-                       return;
+               rx_bd = lp->rx_bd_ci;
+               if (++lp->rx_bd_ci >= RX_BD_NUM)
+                       lp->rx_bd_ci = 0;
+       } while (rx_bd != lp->rx_bd_tail);
+
+       /* DMA operations will halt when the last buffer descriptor is
+        * processed (ie. the one pointed to by RX_TAILDESC_PTR).
+        * When that happens, no more interrupt events will be
+        * generated.  No IRQ_COAL or IRQ_DLY, and not even an
+        * IRQ_ERR.  To avoid stalling, we schedule a delayed work
+        * when there is a potential risk of that happening.  The work
+        * will call this function, and thus re-schedule itself until
+        * enough buffers are available again.
+        */
+       if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx)
+               schedule_delayed_work(&lp->restart_work, HZ / 1000);
+
+       /* Allocate new buffers for those buffer descriptors that were
+        * passed to network stack.  Note that GFP_ATOMIC allocations
+        * can fail (e.g. when a larger burst of GFP_ATOMIC
+        * allocations occurs), so while we try to allocate all
+        * buffers in the same interrupt where they were processed, we
+        * continue with what we could get in case of allocation
+        * failure.  Allocation of remaining buffers will be retried
+        * in following calls.
+        */
+       while (1) {
+               struct sk_buff *skb;
+               struct cdmac_bd *bd;
+               dma_addr_t skb_dma_addr;
+
+               rx_bd = lp->rx_bd_tail + 1;
+               if (rx_bd >= RX_BD_NUM)
+                       rx_bd = 0;
+               bd = &lp->rx_bd_v[rx_bd];
+
+               if (bd->phys)
+                       break;  /* All skb's allocated */
+
+               skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE);
+               if (!skb) {
+                       dev_warn(&ndev->dev, "skb alloc failed\n");
+                       break;
                }
 
-               cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
-               skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data,
+               skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
                                              XTE_MAX_JUMBO_FRAME_SIZE,
                                              DMA_FROM_DEVICE);
-               cur_p->phys = cpu_to_be32(skb_dma_addr);
-               cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
-               lp->rx_skb[lp->rx_bd_ci] = new_skb;
+               if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent,
+                                                  skb_dma_addr))) {
+                       dev_kfree_skb_any(skb);
+                       break;
+               }
 
-               lp->rx_bd_ci++;
-               if (lp->rx_bd_ci >= RX_BD_NUM)
-                       lp->rx_bd_ci = 0;
+               bd->phys = cpu_to_be32(skb_dma_addr);
+               bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
+               bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
+               lp->rx_skb[rx_bd] = skb;
 
-               cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-               bdstat = be32_to_cpu(cur_p->app0);
+               lp->rx_bd_tail = rx_bd;
+               update_tail = true;
+       }
+
+       /* Move tail pointer when buffers have been allocated */
+       if (update_tail) {
+               lp->dma_out(lp, RX_TAILDESC_PTR,
+                       lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail);
        }
-       lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
 
        spin_unlock_irqrestore(&lp->rx_lock, flags);
 }
 
+/* Function scheduled to ensure a restart in case of DMA halt
+ * condition caused by running out of buffer descriptors.
+ */
+static void ll_temac_restart_work_func(struct work_struct *work)
+{
+       struct temac_local *lp = container_of(work, struct temac_local,
+                                             restart_work.work);
+       struct net_device *ndev = lp->ndev;
+
+       ll_temac_recv(ndev);
+}
+
 static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
 {
        struct net_device *ndev = _ndev;
@@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev)
 
        dev_dbg(&ndev->dev, "temac_close()\n");
 
+       cancel_delayed_work_sync(&lp->restart_work);
+
        free_irq(lp->tx_irq, ndev);
        free_irq(lp->rx_irq, ndev);
 
@@ -1173,6 +1301,7 @@ static int temac_probe(struct platform_device *pdev)
        lp->dev = &pdev->dev;
        lp->options = XTE_OPTION_DEFAULTS;
        spin_lock_init(&lp->rx_lock);
+       INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func);
 
        /* Setup mutex for synchronization of indirect register access */
        if (pdata) {
@@ -1279,6 +1408,7 @@ static int temac_probe(struct platform_device *pdev)
                 */
                lp->tx_chnl_ctrl = 0x10220000;
                lp->rx_chnl_ctrl = 0xff070000;
+               lp->coalesce_count_rx = 0x07;
 
                /* Finished with the DMA node; drop the reference */
                of_node_put(dma_np);
@@ -1310,11 +1440,14 @@ static int temac_probe(struct platform_device *pdev)
                                (pdata->tx_irq_count << 16);
                else
                        lp->tx_chnl_ctrl = 0x10220000;
-               if (pdata->rx_irq_timeout || pdata->rx_irq_count)
+               if (pdata->rx_irq_timeout || pdata->rx_irq_count) {
                        lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) |
                                (pdata->rx_irq_count << 16);
-               else
+                       lp->coalesce_count_rx = pdata->rx_irq_count;
+               } else {
                        lp->rx_chnl_ctrl = 0xff070000;
+                       lp->coalesce_count_rx = 0x07;
+               }
        }
 
        /* Error handle returned DMA RX and TX interrupts */
index ae3f308..1b320bc 100644 (file)
@@ -99,7 +99,7 @@ static struct netvsc_device *alloc_net_device(void)
 
        init_waitqueue_head(&net_device->wait_drain);
        net_device->destroy = false;
-       net_device->tx_disable = false;
+       net_device->tx_disable = true;
 
        net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
        net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
index 65e12cb..2c0a24c 100644 (file)
@@ -1068,6 +1068,7 @@ static int netvsc_attach(struct net_device *ndev,
        }
 
        /* In any case device is now ready */
+       nvdev->tx_disable = false;
        netif_device_attach(ndev);
 
        /* Note: enable and attach happen when sub-channels setup */
@@ -2476,6 +2477,8 @@ static int netvsc_probe(struct hv_device *dev,
        else
                net->max_mtu = ETH_DATA_LEN;
 
+       nvdev->tx_disable = false;
+
        ret = register_netdevice(net);
        if (ret != 0) {
                pr_err("Unable to register netdev.\n");
index 30cd0c4..8801d09 100644 (file)
@@ -293,6 +293,7 @@ void ipvlan_process_multicast(struct work_struct *work)
                }
                if (dev)
                        dev_put(dev);
+               cond_resched();
        }
 }
 
@@ -498,19 +499,21 @@ static int ipvlan_process_outbound(struct sk_buff *skb)
        struct ethhdr *ethh = eth_hdr(skb);
        int ret = NET_XMIT_DROP;
 
-       /* In this mode we dont care about multicast and broadcast traffic */
-       if (is_multicast_ether_addr(ethh->h_dest)) {
-               pr_debug_ratelimited("Dropped {multi|broad}cast of type=[%x]\n",
-                                    ntohs(skb->protocol));
-               kfree_skb(skb);
-               goto out;
-       }
-
        /* The ipvlan is a pseudo-L2 device, so the packets that we receive
         * will have L2; which need to discarded and processed further
         * in the net-ns of the main-device.
         */
        if (skb_mac_header_was_set(skb)) {
+               /* In this mode we dont care about
+                * multicast and broadcast traffic */
+               if (is_multicast_ether_addr(ethh->h_dest)) {
+                       pr_debug_ratelimited(
+                               "Dropped {multi|broad}cast of type=[%x]\n",
+                               ntohs(skb->protocol));
+                       kfree_skb(skb);
+                       goto out;
+               }
+
                skb_pull(skb, sizeof(*ethh));
                skb->mac_header = (typeof(skb->mac_header))~0U;
                skb_reset_network_header(skb);
index a706622..f195f27 100644 (file)
@@ -164,7 +164,6 @@ static void ipvlan_uninit(struct net_device *dev)
 static int ipvlan_open(struct net_device *dev)
 {
        struct ipvl_dev *ipvlan = netdev_priv(dev);
-       struct net_device *phy_dev = ipvlan->phy_dev;
        struct ipvl_addr *addr;
 
        if (ipvlan->port->mode == IPVLAN_MODE_L3 ||
@@ -178,7 +177,7 @@ static int ipvlan_open(struct net_device *dev)
                ipvlan_ht_addr_add(ipvlan, addr);
        rcu_read_unlock();
 
-       return dev_uc_add(phy_dev, phy_dev->dev_addr);
+       return 0;
 }
 
 static int ipvlan_stop(struct net_device *dev)
@@ -190,8 +189,6 @@ static int ipvlan_stop(struct net_device *dev)
        dev_uc_unsync(phy_dev, dev);
        dev_mc_unsync(phy_dev, dev);
 
-       dev_uc_del(phy_dev, phy_dev->dev_addr);
-
        rcu_read_lock();
        list_for_each_entry_rcu(addr, &ipvlan->addrs, anode)
                ipvlan_ht_addr_del(addr);
index 45bfd99..6ec6fc1 100644 (file)
@@ -424,6 +424,11 @@ static struct macsec_eth_header *macsec_ethhdr(struct sk_buff *skb)
        return (struct macsec_eth_header *)skb_mac_header(skb);
 }
 
+static sci_t dev_to_sci(struct net_device *dev, __be16 port)
+{
+       return make_sci(dev->dev_addr, port);
+}
+
 static void __macsec_pn_wrapped(struct macsec_secy *secy,
                                struct macsec_tx_sa *tx_sa)
 {
@@ -3268,6 +3273,20 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)
 
 out:
        ether_addr_copy(dev->dev_addr, addr->sa_data);
+       macsec->secy.sci = dev_to_sci(dev, MACSEC_PORT_ES);
+
+       /* If h/w offloading is available, propagate to the device */
+       if (macsec_is_offloaded(macsec)) {
+               const struct macsec_ops *ops;
+               struct macsec_context ctx;
+
+               ops = macsec_get_ops(macsec, &ctx);
+               if (ops) {
+                       ctx.secy = &macsec->secy;
+                       macsec_offload(ops->mdo_upd_secy, &ctx);
+               }
+       }
+
        return 0;
 }
 
@@ -3342,6 +3361,7 @@ static const struct device_type macsec_type = {
 
 static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {
        [IFLA_MACSEC_SCI] = { .type = NLA_U64 },
+       [IFLA_MACSEC_PORT] = { .type = NLA_U16 },
        [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 },
        [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 },
        [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 },
@@ -3592,11 +3612,6 @@ static bool sci_exists(struct net_device *dev, sci_t sci)
        return false;
 }
 
-static sci_t dev_to_sci(struct net_device *dev, __be16 port)
-{
-       return make_sci(dev->dev_addr, port);
-}
-
 static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len)
 {
        struct macsec_dev *macsec = macsec_priv(dev);
index 81aa7ad..e7289d6 100644 (file)
@@ -334,6 +334,8 @@ static void macvlan_process_broadcast(struct work_struct *w)
                if (src)
                        dev_put(src->dev);
                consume_skb(skb);
+
+               cond_resched();
        }
 }
 
index 23f1958..459fb20 100644 (file)
@@ -73,6 +73,7 @@ static struct phy_driver bcm63xx_driver[] = {
        /* same phy as above, with just a different OUI */
        .phy_id         = 0x002bdc00,
        .phy_id_mask    = 0xfffffc00,
+       .name           = "Broadcom BCM63XX (2)",
        /* PHY_BASIC_FEATURES */
        .flags          = PHY_IS_INTERNAL,
        .config_init    = bcm63xx_config_init,
index 28e33ec..9a8bada 100644 (file)
@@ -1306,6 +1306,9 @@ static int marvell_read_status_page_an(struct phy_device *phydev,
                }
        }
 
+       if (!(status & MII_M1011_PHY_STATUS_RESOLVED))
+               return 0;
+
        if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
                phydev->duplex = DUPLEX_FULL;
        else
@@ -1365,6 +1368,8 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
        linkmode_zero(phydev->lp_advertising);
        phydev->pause = 0;
        phydev->asym_pause = 0;
+       phydev->speed = SPEED_UNKNOWN;
+       phydev->duplex = DUPLEX_UNKNOWN;
 
        if (phydev->autoneg == AUTONEG_ENABLE)
                err = marvell_read_status_page_an(phydev, fiber, status);
index 937ac7d..f686f40 100644 (file)
@@ -345,11 +345,11 @@ enum macsec_bank {
                                BIT(VSC8531_FORCE_LED_OFF) | \
                                BIT(VSC8531_FORCE_LED_ON))
 
-#define MSCC_VSC8584_REVB_INT8051_FW           "mscc_vsc8584_revb_int8051_fb48.bin"
+#define MSCC_VSC8584_REVB_INT8051_FW           "microchip/mscc_vsc8584_revb_int8051_fb48.bin"
 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR        0xe800
 #define MSCC_VSC8584_REVB_INT8051_FW_CRC       0xfb48
 
-#define MSCC_VSC8574_REVB_INT8051_FW           "mscc_vsc8574_revb_int8051_29e8.bin"
+#define MSCC_VSC8574_REVB_INT8051_FW           "microchip/mscc_vsc8574_revb_int8051_29e8.bin"
 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR        0x4000
 #define MSCC_VSC8574_REVB_INT8051_FW_CRC       0x29e8
 
index a1caeee..dd2e23f 100644 (file)
@@ -167,7 +167,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
  */
 int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
 {
-       int ret = 0;
+       int ret;
 
        if (!restart) {
                /* Configure and restart aneg if it wasn't set before */
@@ -180,9 +180,9 @@ int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
        }
 
        if (restart)
-               ret = genphy_c45_restart_aneg(phydev);
+               return genphy_c45_restart_aneg(phydev);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
 
index d76e038..355bfde 100644 (file)
@@ -727,7 +727,8 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
                phy_trigger_machine(phydev);
        }
 
-       if (phy_clear_interrupt(phydev))
+       /* did_interrupt() may have cleared the interrupt already */
+       if (!phydev->drv->did_interrupt && phy_clear_interrupt(phydev))
                goto phy_err;
        return IRQ_HANDLED;
 
index 6a5056e..28e3c5c 100644 (file)
@@ -247,7 +247,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
         * MDIO bus driver and clock gated at this point.
         */
        if (!netdev)
-               return !phydev->suspended;
+               goto out;
 
        if (netdev->wol_enabled)
                return false;
@@ -267,7 +267,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
        if (device_may_wakeup(&netdev->dev))
                return false;
 
-       return true;
+out:
+       return !phydev->suspended;
 }
 
 static int mdio_bus_phy_suspend(struct device *dev)
@@ -285,6 +286,8 @@ static int mdio_bus_phy_suspend(struct device *dev)
        if (!mdio_bus_phy_may_suspend(phydev))
                return 0;
 
+       phydev->suspended_by_mdio_bus = 1;
+
        return phy_suspend(phydev);
 }
 
@@ -293,9 +296,11 @@ static int mdio_bus_phy_resume(struct device *dev)
        struct phy_device *phydev = to_phy_device(dev);
        int ret;
 
-       if (!mdio_bus_phy_may_suspend(phydev))
+       if (!phydev->suspended_by_mdio_bus)
                goto no_resume;
 
+       phydev->suspended_by_mdio_bus = 0;
+
        ret = phy_resume(phydev);
        if (ret < 0)
                return ret;
@@ -1792,7 +1797,7 @@ EXPORT_SYMBOL(genphy_restart_aneg);
  */
 int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
 {
-       int ret = 0;
+       int ret;
 
        if (!restart) {
                /* Advertisement hasn't changed, but maybe aneg was never on to
@@ -1807,9 +1812,9 @@ int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
        }
 
        if (restart)
-               ret = genphy_restart_aneg(phydev);
+               return genphy_restart_aneg(phydev);
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(genphy_check_and_restart_aneg);
 
index 70b9a14..6e66b8e 100644 (file)
@@ -761,8 +761,14 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
                config.interface = interface;
 
        ret = phylink_validate(pl, supported, &config);
-       if (ret)
+       if (ret) {
+               phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %d\n",
+                            phy_modes(config.interface),
+                            __ETHTOOL_LINK_MODE_MASK_NBITS, phy->supported,
+                            __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising,
+                            ret);
                return ret;
+       }
 
        phy->phylink = pl;
        phy->phy_link_change = phylink_phy_change;
index 58a69f8..f78ceba 100644 (file)
@@ -232,7 +232,7 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
        struct cstate *cs = lcs->next;
        unsigned long deltaS, deltaA;
        short changes = 0;
-       int hlen;
+       int nlen, hlen;
        unsigned char new_seq[16];
        unsigned char *cp = new_seq;
        struct iphdr *ip;
@@ -248,6 +248,8 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
                return isize;
 
        ip = (struct iphdr *) icp;
+       if (ip->version != 4 || ip->ihl < 5)
+               return isize;
 
        /* Bail if this packet isn't TCP, or is an IP fragment */
        if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
@@ -258,10 +260,14 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
                        comp->sls_o_tcp++;
                return isize;
        }
-       /* Extract TCP header */
+       nlen = ip->ihl * 4;
+       if (isize < nlen + sizeof(*th))
+               return isize;
 
-       th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
-       hlen = ip->ihl*4 + th->doff*4;
+       th = (struct tcphdr *)(icp + nlen);
+       if (th->doff < sizeof(struct tcphdr) / 4)
+               return isize;
+       hlen = nlen + th->doff * 4;
 
        /*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
         *  some other control bit is set). Also uncompressible if
index 6f4d7ba..babb018 100644 (file)
@@ -863,7 +863,10 @@ err_free_chan:
        tty->disc_data = NULL;
        clear_bit(SLF_INUSE, &sl->flags);
        sl_free_netdev(sl->dev);
+       /* do not call free_netdev before rtnl_unlock */
+       rtnl_unlock();
        free_netdev(sl->dev);
+       return err;
 
 err_exit:
        rtnl_unlock();
index ca70a1d..4004f98 100644 (file)
@@ -2240,6 +2240,8 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = {
        [TEAM_ATTR_OPTION_CHANGED]              = { .type = NLA_FLAG },
        [TEAM_ATTR_OPTION_TYPE]                 = { .type = NLA_U8 },
        [TEAM_ATTR_OPTION_DATA]                 = { .type = NLA_BINARY },
+       [TEAM_ATTR_OPTION_PORT_IFINDEX]         = { .type = NLA_U32 },
+       [TEAM_ATTR_OPTION_ARRAY_INDEX]          = { .type = NLA_U32 },
 };
 
 static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
index 3b7a3b8..5754bb6 100644 (file)
@@ -337,6 +337,9 @@ static void qmi_wwan_netdev_setup(struct net_device *net)
                netdev_dbg(net, "mode: raw IP\n");
        } else if (!net->header_ops) { /* don't bother if already set */
                ether_setup(net);
+               /* Restoring min/max mtu values set originally by usbnet */
+               net->min_mtu = 0;
+               net->max_mtu = ETH_MAX_MTU;
                clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
                netdev_dbg(net, "mode: Ethernet\n");
        }
index 78ddbaf..95b19ce 100644 (file)
@@ -3221,6 +3221,8 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired)
                }
 
                msleep(20);
+               if (test_bit(RTL8152_UNPLUG, &tp->flags))
+                       break;
        }
 
        return data;
@@ -5402,7 +5404,10 @@ static void r8153_init(struct r8152 *tp)
                if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
                    AUTOLOAD_DONE)
                        break;
+
                msleep(20);
+               if (test_bit(RTL8152_UNPLUG, &tp->flags))
+                       break;
        }
 
        data = r8153_phy_status(tp, 0);
@@ -5539,7 +5544,10 @@ static void r8153b_init(struct r8152 *tp)
                if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
                    AUTOLOAD_DONE)
                        break;
+
                msleep(20);
+               if (test_bit(RTL8152_UNPLUG, &tp->flags))
+                       break;
        }
 
        data = r8153_phy_status(tp, 0);
index 8cdc441..d4cbb9e 100644 (file)
@@ -328,7 +328,7 @@ static void veth_get_stats64(struct net_device *dev,
        rcu_read_lock();
        peer = rcu_dereference(priv->peer);
        if (peer) {
-               tot->rx_dropped += veth_stats_tx(peer, &packets, &bytes);
+               veth_stats_tx(peer, &packets, &bytes);
                tot->rx_bytes += bytes;
                tot->rx_packets += packets;
 
index 70b29bf..60296a7 100644 (file)
@@ -308,7 +308,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
                }
 
                /* PHY_SKU section is mandatory in B0 */
-               if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
+               if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT &&
+                   !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
                        IWL_ERR(mvm,
                                "Can't parse phy_sku in B0, empty sections\n");
                        return NULL;
index 6173c80..1847f55 100644 (file)
@@ -447,10 +447,13 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
        struct page *page = virt_to_head_page(data);
        int offset = data - page_address(page);
        struct sk_buff *skb = q->rx_head;
+       struct skb_shared_info *shinfo = skb_shinfo(skb);
 
-       offset += q->buf_offset;
-       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len,
-                       q->buf_size);
+       if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) {
+               offset += q->buf_offset;
+               skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len,
+                               q->buf_size);
+       }
 
        if (more)
                return;
index 8270bbf..9f982c0 100644 (file)
@@ -306,6 +306,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                                rc = of_mdiobus_register_phy(mdio, child, addr);
                                if (rc && rc != -ENODEV)
                                        goto unregister;
+                               break;
                        }
                }
        }
index d20aabc..3a10e67 100644 (file)
@@ -670,7 +670,7 @@ static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
         *   outbound memory @ 3GB). So instead it will  start at the 1x
         *   multiple of its size
         */
-       if (!*rc_bar2_size || *rc_bar2_offset % *rc_bar2_size ||
+       if (!*rc_bar2_size || (*rc_bar2_offset & (*rc_bar2_size - 1)) ||
            (*rc_bar2_offset < SZ_4G && *rc_bar2_offset > SZ_2G)) {
                dev_err(dev, "Invalid rc_bar2_offset/size: size 0x%llx, off 0x%llx\n",
                        *rc_bar2_size, *rc_bar2_offset);
index acce878..f5c7a84 100644 (file)
@@ -24,8 +24,6 @@ static int arm_pmu_acpi_register_irq(int cpu)
        int gsi, trigger;
 
        gicc = acpi_cpu_get_madt_gicc(cpu);
-       if (WARN_ON(!gicc))
-               return -EINVAL;
 
        gsi = gicc->performance_interrupt;
 
@@ -64,11 +62,10 @@ static void arm_pmu_acpi_unregister_irq(int cpu)
        int gsi;
 
        gicc = acpi_cpu_get_madt_gicc(cpu);
-       if (!gicc)
-               return;
 
        gsi = gicc->performance_interrupt;
-       acpi_unregister_gsi(gsi);
+       if (gsi)
+               acpi_unregister_gsi(gsi);
 }
 
 #if IS_ENABLED(CONFIG_ARM_SPE_PMU)
index 95dca2c..90884d1 100644 (file)
@@ -388,9 +388,10 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
 
        if (enable) {
                /*
-                * must disable first, then enable again
-                * otherwise, cycle counter will not work
-                * if previous state is enabled.
+                * cycle counter is special which should firstly write 0 then
+                * write 1 into CLEAR bit to clear it. Other counters only
+                * need write 0 into CLEAR bit and it turns out to be 1 by
+                * hardware. Below enable flow is harmless for all counters.
                 */
                writel(0, pmu->base + reg);
                val = CNTL_EN | CNTL_CLEAR;
@@ -398,7 +399,8 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
                writel(val, pmu->base + reg);
        } else {
                /* Disable counter */
-               writel(0, pmu->base + reg);
+               val = readl_relaxed(pmu->base + reg) & CNTL_EN_MASK;
+               writel(val, pmu->base + reg);
        }
 }
 
index 1169f3e..b1c04f7 100644 (file)
@@ -49,7 +49,7 @@
 #define SUNXI_LOS_BIAS(n)              ((n) << 3)
 #define SUNXI_LOS_BIAS_MASK            GENMASK(5, 3)
 #define SUNXI_TXVBOOSTLVL(n)           ((n) << 0)
-#define SUNXI_TXVBOOSTLVL_MASK         GENMASK(0, 2)
+#define SUNXI_TXVBOOSTLVL_MASK         GENMASK(2, 0)
 
 struct sun50i_usb3_phy {
        struct phy *phy;
index 4710cfc..18251f2 100644 (file)
@@ -186,29 +186,6 @@ enum sata_phy_ctrl_regs {
        PHY_CTRL_1_RESET                        = BIT(0),
 };
 
-static inline void __iomem *brcm_sata_pcb_base(struct brcm_sata_port *port)
-{
-       struct brcm_sata_phy *priv = port->phy_priv;
-       u32 size = 0;
-
-       switch (priv->version) {
-       case BRCM_SATA_PHY_STB_16NM:
-       case BRCM_SATA_PHY_STB_28NM:
-       case BRCM_SATA_PHY_IPROC_NS2:
-       case BRCM_SATA_PHY_DSL_28NM:
-               size = SATA_PCB_REG_28NM_SPACE_SIZE;
-               break;
-       case BRCM_SATA_PHY_STB_40NM:
-               size = SATA_PCB_REG_40NM_SPACE_SIZE;
-               break;
-       default:
-               dev_err(priv->dev, "invalid phy version\n");
-               break;
-       }
-
-       return priv->phy_base + (port->portnum * size);
-}
-
 static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
 {
        struct brcm_sata_phy *priv = port->phy_priv;
@@ -226,19 +203,34 @@ static inline void __iomem *brcm_sata_ctrl_base(struct brcm_sata_port *port)
        return priv->ctrl_base + (port->portnum * size);
 }
 
-static void brcm_sata_phy_wr(void __iomem *pcb_base, u32 bank,
+static void brcm_sata_phy_wr(struct brcm_sata_port *port, u32 bank,
                             u32 ofs, u32 msk, u32 value)
 {
+       struct brcm_sata_phy *priv = port->phy_priv;
+       void __iomem *pcb_base = priv->phy_base;
        u32 tmp;
 
+       if (priv->version == BRCM_SATA_PHY_STB_40NM)
+               bank += (port->portnum * SATA_PCB_REG_40NM_SPACE_SIZE);
+       else
+               pcb_base += (port->portnum * SATA_PCB_REG_28NM_SPACE_SIZE);
+
        writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
        tmp = readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
        tmp = (tmp & msk) | value;
        writel(tmp, pcb_base + SATA_PCB_REG_OFFSET(ofs));
 }
 
-static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
+static u32 brcm_sata_phy_rd(struct brcm_sata_port *port, u32 bank, u32 ofs)
 {
+       struct brcm_sata_phy *priv = port->phy_priv;
+       void __iomem *pcb_base = priv->phy_base;
+
+       if (priv->version == BRCM_SATA_PHY_STB_40NM)
+               bank += (port->portnum * SATA_PCB_REG_40NM_SPACE_SIZE);
+       else
+               pcb_base += (port->portnum * SATA_PCB_REG_28NM_SPACE_SIZE);
+
        writel(bank, pcb_base + SATA_PCB_BANK_OFFSET);
        return readl(pcb_base + SATA_PCB_REG_OFFSET(ofs));
 }
@@ -250,16 +242,15 @@ static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
 
 static void brcm_stb_sata_ssc_init(struct brcm_sata_port *port)
 {
-       void __iomem *base = brcm_sata_pcb_base(port);
        struct brcm_sata_phy *priv = port->phy_priv;
        u32 tmp;
 
        /* override the TX spread spectrum setting */
        tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC;
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
+       brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp);
 
        /* set fixed min freq */
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
+       brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2,
                         ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK,
                         STB_FMIN_VAL_DEFAULT);
 
@@ -271,7 +262,7 @@ static void brcm_stb_sata_ssc_init(struct brcm_sata_port *port)
                tmp = STB_FMAX_VAL_DEFAULT;
        }
 
-       brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
+       brcm_sata_phy_wr(port, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
                          ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
 }
 
@@ -280,7 +271,6 @@ static void brcm_stb_sata_ssc_init(struct brcm_sata_port *port)
 
 static int brcm_stb_sata_rxaeq_init(struct brcm_sata_port *port)
 {
-       void __iomem *base = brcm_sata_pcb_base(port);
        u32 tmp = 0, reg = 0;
 
        switch (port->rxaeq_mode) {
@@ -301,8 +291,8 @@ static int brcm_stb_sata_rxaeq_init(struct brcm_sata_port *port)
                break;
        }
 
-       brcm_sata_phy_wr(base, AEQRX_REG_BANK_0, reg, ~tmp, tmp);
-       brcm_sata_phy_wr(base, AEQRX_REG_BANK_1, reg, ~tmp, tmp);
+       brcm_sata_phy_wr(port, AEQRX_REG_BANK_0, reg, ~tmp, tmp);
+       brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, reg, ~tmp, tmp);
 
        return 0;
 }
@@ -316,18 +306,17 @@ static int brcm_stb_sata_init(struct brcm_sata_port *port)
 
 static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
 {
-       void __iomem *base = brcm_sata_pcb_base(port);
        u32 tmp, value;
 
        /* Reduce CP tail current to 1/16th of its default value */
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0x141);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0x141);
 
        /* Turn off CP tail current boost */
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL8, 0, 0xc006);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL8, 0, 0xc006);
 
        /* Set a specific AEQ equalizer value */
        tmp = AEQ_FRC_EQ_FORCE_VAL | AEQ_FRC_EQ_FORCE;
-       brcm_sata_phy_wr(base, AEQRX_REG_BANK_0, AEQ_FRC_EQ,
+       brcm_sata_phy_wr(port, AEQRX_REG_BANK_0, AEQ_FRC_EQ,
                         ~(tmp | AEQ_RFZ_FRC_VAL |
                           AEQ_FRC_EQ_VAL_MASK << AEQ_FRC_EQ_VAL_SHIFT),
                         tmp | 32 << AEQ_FRC_EQ_VAL_SHIFT);
@@ -337,7 +326,7 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
                value = 0x52;
        else
                value = 0;
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_CDR_CONTROL1,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CONTROL1,
                         ~RXPMD_RX_PPM_VAL_MASK, value);
 
        /* Set proportional loop bandwith Gen1/2/3 */
@@ -352,7 +341,7 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
                value = 1 << RXPMD_G1_CDR_PROP_BW_SHIFT |
                        1 << RXPMD_G2_CDR_PROP_BW_SHIFT |
                        1 << RXPMD_G3_CDR_PROB_BW_SHIFT;
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_PROP_BW, ~tmp,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_PROP_BW, ~tmp,
                         value);
 
        /* Set CDR integral loop acquisition bandwidth for Gen1/2/3 */
@@ -365,7 +354,7 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
                        1 << RXPMD_G3_CDR_ACQ_INT_BW_SHIFT;
        else
                value = 0;
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_ACQ_INTEG_BW,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_ACQ_INTEG_BW,
                         ~tmp, value);
 
        /* Set CDR integral loop locking bandwidth to 1 for Gen 1/2/3 */
@@ -378,7 +367,7 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
                        1 << RXPMD_G3_CDR_LOCK_INT_BW_SHIFT;
        else
                value = 0;
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_LOCK_INTEG_BW,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_CDR_CDR_LOCK_INTEG_BW,
                         ~tmp, value);
 
        /* Set no guard band and clamp CDR */
@@ -387,11 +376,11 @@ static int brcm_stb_sata_16nm_ssc_init(struct brcm_sata_port *port)
                value = 0x51;
        else
                value = 0;
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
                         ~tmp, RXPMD_MON_CORRECT_EN | value);
 
        /* Turn on/off SSC */
-       brcm_sata_phy_wr(base, TX_REG_BANK, TX_ACTRL5, ~TX_ACTRL5_SSC_EN,
+       brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL5, ~TX_ACTRL5_SSC_EN,
                         port->ssc_en ? TX_ACTRL5_SSC_EN : 0);
 
        return 0;
@@ -411,7 +400,6 @@ static int brcm_ns2_sata_init(struct brcm_sata_port *port)
 {
        int try;
        unsigned int val;
-       void __iomem *base = brcm_sata_pcb_base(port);
        void __iomem *ctrl_base = brcm_sata_ctrl_base(port);
        struct device *dev = port->phy_priv->dev;
 
@@ -421,24 +409,24 @@ static int brcm_ns2_sata_init(struct brcm_sata_port *port)
        val |= (0x4 << OOB_CTRL1_BURST_MIN_SHIFT);
        val |= (0x9 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
        val |= (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
+       brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
        val = 0x0;
        val |= (0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
        val |= (0x2 << OOB_CTRL2_BURST_CNT_SHIFT);
        val |= (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
+       brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
 
        /* Configure PHY PLL register bank 1 */
        val = NS2_PLL1_ACTRL2_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
        val = NS2_PLL1_ACTRL3_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
        val = NS2_PLL1_ACTRL4_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
 
        /* Configure PHY BLOCK0 register bank */
        /* Set oob_clk_sel to refclk/2 */
-       brcm_sata_phy_wr(base, BLOCK0_REG_BANK, BLOCK0_SPARE,
+       brcm_sata_phy_wr(port, BLOCK0_REG_BANK, BLOCK0_SPARE,
                         ~BLOCK0_SPARE_OOB_CLK_SEL_MASK,
                         BLOCK0_SPARE_OOB_CLK_SEL_REFBY2);
 
@@ -451,7 +439,7 @@ static int brcm_ns2_sata_init(struct brcm_sata_port *port)
        /* Wait for PHY PLL lock by polling pll_lock bit */
        try = 50;
        while (try) {
-               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+               val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
                                        BLOCK0_XGXSSTATUS);
                if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
                        break;
@@ -471,9 +459,7 @@ static int brcm_ns2_sata_init(struct brcm_sata_port *port)
 
 static int brcm_nsp_sata_init(struct brcm_sata_port *port)
 {
-       struct brcm_sata_phy *priv = port->phy_priv;
        struct device *dev = port->phy_priv->dev;
-       void __iomem *base = priv->phy_base;
        unsigned int oob_bank;
        unsigned int val, try;
 
@@ -490,36 +476,36 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
        val |= (0x06 << OOB_CTRL1_BURST_MIN_SHIFT);
        val |= (0x0f << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT);
        val |= (0x06 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL1, 0x0, val);
+       brcm_sata_phy_wr(port, oob_bank, OOB_CTRL1, 0x0, val);
 
        val = 0x0;
        val |= (0x2e << OOB_CTRL2_RESET_IDLE_MAX_SHIFT);
        val |= (0x02 << OOB_CTRL2_BURST_CNT_SHIFT);
        val |= (0x16 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT);
-       brcm_sata_phy_wr(base, oob_bank, OOB_CTRL2, 0x0, val);
+       brcm_sata_phy_wr(port, oob_bank, OOB_CTRL2, 0x0, val);
 
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL2,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_ACTRL2,
                ~(PLL_ACTRL2_SELDIV_MASK << PLL_ACTRL2_SELDIV_SHIFT),
                0x0c << PLL_ACTRL2_SELDIV_SHIFT);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CONTROL,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_CAP_CONTROL,
                                                0xff0, 0x4f0);
 
        val = PLLCONTROL_0_FREQ_DET_RESTART | PLLCONTROL_0_FREQ_MONITOR;
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
                                                                ~val, val);
        val = PLLCONTROL_0_SEQ_START;
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
                                                                ~val, 0);
        mdelay(10);
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
                                                                ~val, val);
 
        /* Wait for pll_seq_done bit */
        try = 50;
        while (--try) {
-               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+               val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
                                        BLOCK0_XGXSSTATUS);
                if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
                        break;
@@ -546,27 +532,25 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
 
 static int brcm_sr_sata_init(struct brcm_sata_port *port)
 {
-       struct brcm_sata_phy *priv = port->phy_priv;
        struct device *dev = port->phy_priv->dev;
-       void __iomem *base = priv->phy_base;
        unsigned int val, try;
 
        /* Configure PHY PLL register bank 1 */
        val = SR_PLL1_ACTRL2_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL2, 0x0, val);
        val = SR_PLL1_ACTRL3_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL3, 0x0, val);
        val = SR_PLL1_ACTRL4_MAGIC;
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL4, 0x0, val);
 
        /* Configure PHY PLL register bank 0 */
        val = SR_PLL0_ACTRL6_MAGIC;
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_ACTRL6, 0x0, val);
 
        /* Wait for PHY PLL lock by polling pll_lock bit */
        try = 50;
        do {
-               val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+               val = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
                                        BLOCK0_XGXSSTATUS);
                if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
                        break;
@@ -581,7 +565,7 @@ static int brcm_sr_sata_init(struct brcm_sata_port *port)
        }
 
        /* Invert Tx polarity */
-       brcm_sata_phy_wr(base, TX_REG_BANK, TX_ACTRL0,
+       brcm_sata_phy_wr(port, TX_REG_BANK, TX_ACTRL0,
                         ~TX_ACTRL0_TXPOL_FLIP, TX_ACTRL0_TXPOL_FLIP);
 
        /* Configure OOB control to handle 100MHz reference clock */
@@ -589,52 +573,51 @@ static int brcm_sr_sata_init(struct brcm_sata_port *port)
                (0x4 << OOB_CTRL1_BURST_MIN_SHIFT) |
                (0x8 << OOB_CTRL1_WAKE_IDLE_MAX_SHIFT) |
                (0x3 << OOB_CTRL1_WAKE_IDLE_MIN_SHIFT));
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
+       brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL1, 0x0, val);
        val = ((0x1b << OOB_CTRL2_RESET_IDLE_MAX_SHIFT) |
                (0x2 << OOB_CTRL2_BURST_CNT_SHIFT) |
                (0x9 << OOB_CTRL2_RESET_IDLE_MIN_SHIFT));
-       brcm_sata_phy_wr(base, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
+       brcm_sata_phy_wr(port, OOB_REG_BANK, OOB_CTRL2, 0x0, val);
 
        return 0;
 }
 
 static int brcm_dsl_sata_init(struct brcm_sata_port *port)
 {
-       void __iomem *base = brcm_sata_pcb_base(port);
        struct device *dev = port->phy_priv->dev;
        unsigned int try;
        u32 tmp;
 
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL7, 0, 0x873);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL7, 0, 0x873);
 
-       brcm_sata_phy_wr(base, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0xc000);
+       brcm_sata_phy_wr(port, PLL1_REG_BANK, PLL1_ACTRL6, 0, 0xc000);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
                         0, 0x3089);
        usleep_range(1000, 2000);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_REG_BANK_0_PLLCONTROL_0,
                         0, 0x3088);
        usleep_range(1000, 2000);
 
-       brcm_sata_phy_wr(base, AEQRX_REG_BANK_1, AEQRX_SLCAL0_CTRL0,
+       brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, AEQRX_SLCAL0_CTRL0,
                         0, 0x3000);
 
-       brcm_sata_phy_wr(base, AEQRX_REG_BANK_1, AEQRX_SLCAL1_CTRL0,
+       brcm_sata_phy_wr(port, AEQRX_REG_BANK_1, AEQRX_SLCAL1_CTRL0,
                         0, 0x3000);
        usleep_range(1000, 2000);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_CAP_CHARGE_TIME, 0, 0x32);
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_CAP_CHARGE_TIME, 0, 0x32);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_VCO_CAL_THRESH, 0, 0xa);
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_VCO_CAL_THRESH, 0, 0xa);
 
-       brcm_sata_phy_wr(base, PLL_REG_BANK_0, PLL_FREQ_DET_TIME, 0, 0x64);
+       brcm_sata_phy_wr(port, PLL_REG_BANK_0, PLL_FREQ_DET_TIME, 0, 0x64);
        usleep_range(1000, 2000);
 
        /* Acquire PLL lock */
        try = 50;
        while (try) {
-               tmp = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
+               tmp = brcm_sata_phy_rd(port, BLOCK0_REG_BANK,
                                       BLOCK0_XGXSSTATUS);
                if (tmp & BLOCK0_XGXSSTATUS_PLL_LOCK)
                        break;
@@ -687,10 +670,9 @@ static int brcm_sata_phy_init(struct phy *phy)
 
 static void brcm_stb_sata_calibrate(struct brcm_sata_port *port)
 {
-       void __iomem *base = brcm_sata_pcb_base(port);
        u32 tmp = BIT(8);
 
-       brcm_sata_phy_wr(base, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
+       brcm_sata_phy_wr(port, RXPMD_REG_BANK, RXPMD_RX_FREQ_MON_CONTROL1,
                         ~tmp, tmp);
 }
 
index f20524f..94a34cf 100644 (file)
@@ -20,6 +20,7 @@
 
 #define PHY_MDM6600_PHY_DELAY_MS       4000    /* PHY enable 2.2s to 3.5s */
 #define PHY_MDM6600_ENABLED_DELAY_MS   8000    /* 8s more total for MDM6600 */
+#define PHY_MDM6600_WAKE_KICK_MS       600     /* time on after GPIO toggle */
 #define MDM6600_MODEM_IDLE_DELAY_MS    1000    /* modem after USB suspend */
 #define MDM6600_MODEM_WAKE_DELAY_MS    200     /* modem response after idle */
 
@@ -243,10 +244,24 @@ static irqreturn_t phy_mdm6600_wakeirq_thread(int irq, void *data)
 {
        struct phy_mdm6600 *ddata = data;
        struct gpio_desc *mode_gpio1;
+       int error, wakeup;
 
        mode_gpio1 = ddata->mode_gpios->desc[PHY_MDM6600_MODE1];
-       dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n",
-               gpiod_get_value(mode_gpio1));
+       wakeup = gpiod_get_value(mode_gpio1);
+       if (!wakeup)
+               return IRQ_NONE;
+
+       dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n", wakeup);
+       error = pm_runtime_get_sync(ddata->dev);
+       if (error < 0) {
+               pm_runtime_put_noidle(ddata->dev);
+
+               return IRQ_NONE;
+       }
+
+       /* Just wake-up and kick the autosuspend timer */
+       pm_runtime_mark_last_busy(ddata->dev);
+       pm_runtime_put_autosuspend(ddata->dev);
 
        return IRQ_HANDLED;
 }
@@ -496,8 +511,14 @@ static void phy_mdm6600_modem_wake(struct work_struct *work)
 
        ddata = container_of(work, struct phy_mdm6600, modem_wake_work.work);
        phy_mdm6600_wake_modem(ddata);
+
+       /*
+        * The modem does not always stay awake 1.2 seconds after toggling
+        * the wake GPIO, and sometimes it idles after about some 600 ms
+        * making writes time out.
+        */
        schedule_delayed_work(&ddata->modem_wake_work,
-                             msecs_to_jiffies(MDM6600_MODEM_IDLE_DELAY_MS));
+                             msecs_to_jiffies(PHY_MDM6600_WAKE_KICK_MS));
 }
 
 static int __maybe_unused phy_mdm6600_runtime_suspend(struct device *dev)
index cd5a6c9..a27b8d5 100644 (file)
@@ -688,11 +688,9 @@ struct phy *phy_get(struct device *dev, const char *string)
        get_device(&phy->dev);
 
        link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
-       if (!link) {
-               dev_err(dev, "failed to create device link to %s\n",
+       if (!link)
+               dev_dbg(dev, "failed to create device link to %s\n",
                        dev_name(phy->dev.parent));
-               return ERR_PTR(-EINVAL);
-       }
 
        return phy;
 }
@@ -803,11 +801,9 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
        }
 
        link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
-       if (!link) {
-               dev_err(dev, "failed to create device link to %s\n",
+       if (!link)
+               dev_dbg(dev, "failed to create device link to %s\n",
                        dev_name(phy->dev.parent));
-               return ERR_PTR(-EINVAL);
-       }
 
        return phy;
 }
@@ -852,11 +848,9 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
        devres_add(dev, ptr);
 
        link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
-       if (!link) {
-               dev_err(dev, "failed to create device link to %s\n",
+       if (!link)
+               dev_dbg(dev, "failed to create device link to %s\n",
                        dev_name(phy->dev.parent));
-               return ERR_PTR(-EINVAL);
-       }
 
        return phy;
 }
index a28bd15..1c536fc 100644 (file)
@@ -80,20 +80,20 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
                break;
 
        case PHY_INTERFACE_MODE_MII:
-               mode = AM33XX_GMII_SEL_MODE_MII;
+       case PHY_INTERFACE_MODE_GMII:
+               gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII;
                break;
 
        default:
-               dev_warn(dev,
-                        "port%u: unsupported mode: \"%s\". Defaulting to MII.\n",
-                        if_phy->id, phy_modes(rgmii_id));
+               dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
+                        if_phy->id, phy_modes(submode));
                return -EINVAL;
        }
 
        if_phy->phy_if_mode = submode;
 
        dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n",
-               __func__, if_phy->id, mode, rgmii_id,
+               __func__, if_phy->id, submode, rgmii_id,
                if_phy->rmii_clock_external);
 
        regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE];
index 7b6409e..dce2626 100644 (file)
@@ -1073,13 +1073,26 @@ static int madera_pin_probe(struct platform_device *pdev)
                return ret;
        }
 
+       platform_set_drvdata(pdev, priv);
+
        dev_dbg(priv->dev, "pinctrl probed ok\n");
 
        return 0;
 }
 
+static int madera_pin_remove(struct platform_device *pdev)
+{
+       struct madera_pin_private *priv = platform_get_drvdata(pdev);
+
+       if (priv->madera->pdata.gpio_configs)
+               pinctrl_unregister_mappings(priv->madera->pdata.gpio_configs);
+
+       return 0;
+}
+
 static struct platform_driver madera_pin_driver = {
        .probe = madera_pin_probe,
+       .remove = madera_pin_remove,
        .driver = {
                .name = "madera-pinctrl",
        },
index 446d84f..f23c55e 100644 (file)
@@ -2021,7 +2021,6 @@ static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
                return PTR_ERR(pctldev->p);
        }
 
-       kref_get(&pctldev->p->users);
        pctldev->hog_default =
                pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
        if (IS_ERR(pctldev->hog_default)) {
index 73bf1d9..23cf04b 100644 (file)
@@ -23,12 +23,12 @@ struct imx_sc_msg_req_pad_set {
        struct imx_sc_rpc_msg hdr;
        u32 val;
        u16 pad;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_pad_get {
        struct imx_sc_rpc_msg hdr;
        u16 pad;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_resp_pad_get {
        struct imx_sc_rpc_msg hdr;
index 1b6e864..2ac921c 100644 (file)
@@ -147,8 +147,8 @@ static const unsigned int sdio_d0_pins[]    = { GPIOX_0 };
 static const unsigned int sdio_d1_pins[]       = { GPIOX_1 };
 static const unsigned int sdio_d2_pins[]       = { GPIOX_2 };
 static const unsigned int sdio_d3_pins[]       = { GPIOX_3 };
-static const unsigned int sdio_cmd_pins[]      = { GPIOX_4 };
-static const unsigned int sdio_clk_pins[]      = { GPIOX_5 };
+static const unsigned int sdio_clk_pins[]      = { GPIOX_4 };
+static const unsigned int sdio_cmd_pins[]      = { GPIOX_5 };
 static const unsigned int sdio_irq_pins[]      = { GPIOX_7 };
 
 static const unsigned int nand_ce0_pins[]      = { BOOT_8 };
index a454f57..62c02b9 100644 (file)
@@ -451,7 +451,7 @@ static int pinctrl_falcon_probe(struct platform_device *pdev)
                falcon_info.clk[*bank] = clk_get(&ppdev->dev, NULL);
                if (IS_ERR(falcon_info.clk[*bank])) {
                        dev_err(&ppdev->dev, "failed to get clock\n");
-                       of_node_put(np)
+                       of_node_put(np);
                        return PTR_ERR(falcon_info.clk[*bank]);
                }
                falcon_info.membase[*bank] = devm_ioremap_resource(&pdev->dev,
index 9a8daa2..1a948c3 100644 (file)
@@ -1104,7 +1104,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
        pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
        pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
        pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
-       pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent;
        pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;
        pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;
        pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;
@@ -1118,7 +1117,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
                if (!chip->irq.parent_domain)
                        return -EPROBE_DEFER;
                chip->irq.child_to_parent_hwirq = msm_gpio_wakeirq;
-
+               pctrl->irq_chip.irq_eoi = irq_chip_eoi_parent;
                /*
                 * Let's skip handling the GPIOs, if the parent irqchip
                 * is handling the direct connect IRQ of the GPIO.
index fba1d41..338a15d 100644 (file)
@@ -794,7 +794,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
        girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node);
        girq->parent_domain = parent_domain;
        girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq;
-       girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell;
+       girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell;
        girq->child_offset_to_irq = pm8xxx_child_offset_to_irq;
        girq->child_irq_domain_ops.translate = pm8xxx_domain_translate;
 
index e69682c..62f2761 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <linux/platform_data/wilco-ec.h>
 #include <linux/string.h>
-#include <linux/unaligned/le_memmove.h>
+#include <asm/unaligned.h>
 
 /* Operation code; what the EC should do with the property */
 enum ec_property_op {
index bdfaf7e..992bc18 100644 (file)
@@ -88,7 +88,7 @@ static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
        }
 
        val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
-       val = (val & ~STM32_ENVR) | STM32_HIZ;
+       val &= ~STM32_ENVR;
        writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
 
        pm_runtime_mark_last_busy(priv->dev);
@@ -175,6 +175,7 @@ static const struct regulator_desc stm32_vrefbuf_regu = {
        .volt_table = stm32_vrefbuf_voltages,
        .n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages),
        .ops = &stm32_vrefbuf_volt_ops,
+       .off_on_delay = 1000,
        .type = REGULATOR_VOLTAGE,
        .owner = THIS_MODULE,
 };
index 461b0e5..d9efbfd 100644 (file)
@@ -51,6 +51,7 @@ config RESET_BRCMSTB
 
 config RESET_BRCMSTB_RESCAL
        bool "Broadcom STB RESCAL reset controller"
+       depends on HAS_IOMEM
        default ARCH_BRCMSTB || COMPILE_TEST
        help
          This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
@@ -73,7 +74,7 @@ config RESET_IMX7
 
 config RESET_INTEL_GW
        bool "Intel Reset Controller Driver"
-       depends on OF
+       depends on OF && HAS_IOMEM
        select REGMAP_MMIO
        help
          This enables the reset controller driver for Intel Gateway SoCs.
index 9575a62..468cada 100644 (file)
@@ -369,7 +369,7 @@ enum qeth_qdio_info_states {
 struct qeth_buffer_pool_entry {
        struct list_head list;
        struct list_head init_list;
-       void *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
+       struct page *elements[QDIO_MAX_ELEMENTS_PER_BUFFER];
 };
 
 struct qeth_qdio_buffer_pool {
@@ -983,7 +983,7 @@ extern const struct attribute_group qeth_device_blkt_group;
 extern const struct device_type qeth_generic_devtype;
 
 const char *qeth_get_cardname_short(struct qeth_card *);
-int qeth_realloc_buffer_pool(struct qeth_card *, int);
+int qeth_resize_buffer_pool(struct qeth_card *card, unsigned int count);
 int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
 void qeth_core_free_discipline(struct qeth_card *);
 
index 8ca85c8..6d3f2f1 100644 (file)
@@ -65,7 +65,6 @@ static struct lock_class_key qdio_out_skb_queue_key;
 static void qeth_issue_next_read_cb(struct qeth_card *card,
                                    struct qeth_cmd_buffer *iob,
                                    unsigned int data_length);
-static void qeth_free_buffer_pool(struct qeth_card *);
 static int qeth_qdio_establish(struct qeth_card *);
 static void qeth_free_qdio_queues(struct qeth_card *card);
 static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
@@ -212,49 +211,121 @@ void qeth_clear_working_pool_list(struct qeth_card *card)
 }
 EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
 
+static void qeth_free_pool_entry(struct qeth_buffer_pool_entry *entry)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(entry->elements); i++) {
+               if (entry->elements[i])
+                       __free_page(entry->elements[i]);
+       }
+
+       kfree(entry);
+}
+
+static void qeth_free_buffer_pool(struct qeth_card *card)
+{
+       struct qeth_buffer_pool_entry *entry, *tmp;
+
+       list_for_each_entry_safe(entry, tmp, &card->qdio.init_pool.entry_list,
+                                init_list) {
+               list_del(&entry->init_list);
+               qeth_free_pool_entry(entry);
+       }
+}
+
+static struct qeth_buffer_pool_entry *qeth_alloc_pool_entry(unsigned int pages)
+{
+       struct qeth_buffer_pool_entry *entry;
+       unsigned int i;
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               return NULL;
+
+       for (i = 0; i < pages; i++) {
+               entry->elements[i] = alloc_page(GFP_KERNEL);
+
+               if (!entry->elements[i]) {
+                       qeth_free_pool_entry(entry);
+                       return NULL;
+               }
+       }
+
+       return entry;
+}
+
 static int qeth_alloc_buffer_pool(struct qeth_card *card)
 {
-       struct qeth_buffer_pool_entry *pool_entry;
-       void *ptr;
-       int i, j;
+       unsigned int buf_elements = QETH_MAX_BUFFER_ELEMENTS(card);
+       unsigned int i;
 
        QETH_CARD_TEXT(card, 5, "alocpool");
        for (i = 0; i < card->qdio.init_pool.buf_count; ++i) {
-               pool_entry = kzalloc(sizeof(*pool_entry), GFP_KERNEL);
-               if (!pool_entry) {
+               struct qeth_buffer_pool_entry *entry;
+
+               entry = qeth_alloc_pool_entry(buf_elements);
+               if (!entry) {
                        qeth_free_buffer_pool(card);
                        return -ENOMEM;
                }
-               for (j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j) {
-                       ptr = (void *) __get_free_page(GFP_KERNEL);
-                       if (!ptr) {
-                               while (j > 0)
-                                       free_page((unsigned long)
-                                                 pool_entry->elements[--j]);
-                               kfree(pool_entry);
-                               qeth_free_buffer_pool(card);
-                               return -ENOMEM;
-                       }
-                       pool_entry->elements[j] = ptr;
-               }
-               list_add(&pool_entry->init_list,
-                        &card->qdio.init_pool.entry_list);
+
+               list_add(&entry->init_list, &card->qdio.init_pool.entry_list);
        }
        return 0;
 }
 
-int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
+int qeth_resize_buffer_pool(struct qeth_card *card, unsigned int count)
 {
+       unsigned int buf_elements = QETH_MAX_BUFFER_ELEMENTS(card);
+       struct qeth_qdio_buffer_pool *pool = &card->qdio.init_pool;
+       struct qeth_buffer_pool_entry *entry, *tmp;
+       int delta = count - pool->buf_count;
+       LIST_HEAD(entries);
+
        QETH_CARD_TEXT(card, 2, "realcbp");
 
-       /* TODO: steel/add buffers from/to a running card's buffer pool (?) */
-       qeth_clear_working_pool_list(card);
-       qeth_free_buffer_pool(card);
-       card->qdio.in_buf_pool.buf_count = bufcnt;
-       card->qdio.init_pool.buf_count = bufcnt;
-       return qeth_alloc_buffer_pool(card);
+       /* Defer until queue is allocated: */
+       if (!card->qdio.in_q)
+               goto out;
+
+       /* Remove entries from the pool: */
+       while (delta < 0) {
+               entry = list_first_entry(&pool->entry_list,
+                                        struct qeth_buffer_pool_entry,
+                                        init_list);
+               list_del(&entry->init_list);
+               qeth_free_pool_entry(entry);
+
+               delta++;
+       }
+
+       /* Allocate additional entries: */
+       while (delta > 0) {
+               entry = qeth_alloc_pool_entry(buf_elements);
+               if (!entry) {
+                       list_for_each_entry_safe(entry, tmp, &entries,
+                                                init_list) {
+                               list_del(&entry->init_list);
+                               qeth_free_pool_entry(entry);
+                       }
+
+                       return -ENOMEM;
+               }
+
+               list_add(&entry->init_list, &entries);
+
+               delta--;
+       }
+
+       list_splice(&entries, &pool->entry_list);
+
+out:
+       card->qdio.in_buf_pool.buf_count = count;
+       pool->buf_count = count;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool);
+EXPORT_SYMBOL_GPL(qeth_resize_buffer_pool);
 
 static void qeth_free_qdio_queue(struct qeth_qdio_q *q)
 {
@@ -1170,19 +1241,6 @@ void qeth_drain_output_queues(struct qeth_card *card)
 }
 EXPORT_SYMBOL_GPL(qeth_drain_output_queues);
 
-static void qeth_free_buffer_pool(struct qeth_card *card)
-{
-       struct qeth_buffer_pool_entry *pool_entry, *tmp;
-       int i = 0;
-       list_for_each_entry_safe(pool_entry, tmp,
-                                &card->qdio.init_pool.entry_list, init_list){
-               for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i)
-                       free_page((unsigned long)pool_entry->elements[i]);
-               list_del(&pool_entry->init_list);
-               kfree(pool_entry);
-       }
-}
-
 static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
 {
        unsigned int count = single ? 1 : card->dev->num_tx_queues;
@@ -1204,7 +1262,6 @@ static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
        if (count == 1)
                dev_info(&card->gdev->dev, "Priority Queueing not supported\n");
 
-       card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE;
        card->qdio.no_out_queues = count;
        return 0;
 }
@@ -2393,7 +2450,6 @@ static void qeth_free_qdio_queues(struct qeth_card *card)
                return;
 
        qeth_free_cq(card);
-       cancel_delayed_work_sync(&card->buffer_reclaim_work);
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
                if (card->qdio.in_q->bufs[j].rx_skb)
                        dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb);
@@ -2575,7 +2631,6 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
        struct list_head *plh;
        struct qeth_buffer_pool_entry *entry;
        int i, free;
-       struct page *page;
 
        if (list_empty(&card->qdio.in_buf_pool.entry_list))
                return NULL;
@@ -2584,7 +2639,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
                entry = list_entry(plh, struct qeth_buffer_pool_entry, list);
                free = 1;
                for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
-                       if (page_count(virt_to_page(entry->elements[i])) > 1) {
+                       if (page_count(entry->elements[i]) > 1) {
                                free = 0;
                                break;
                        }
@@ -2599,15 +2654,15 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
        entry = list_entry(card->qdio.in_buf_pool.entry_list.next,
                        struct qeth_buffer_pool_entry, list);
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
-               if (page_count(virt_to_page(entry->elements[i])) > 1) {
-                       page = alloc_page(GFP_ATOMIC);
-                       if (!page) {
+               if (page_count(entry->elements[i]) > 1) {
+                       struct page *page = alloc_page(GFP_ATOMIC);
+
+                       if (!page)
                                return NULL;
-                       } else {
-                               free_page((unsigned long)entry->elements[i]);
-                               entry->elements[i] = page_address(page);
-                               QETH_CARD_STAT_INC(card, rx_sg_alloc_page);
-                       }
+
+                       __free_page(entry->elements[i]);
+                       entry->elements[i] = page;
+                       QETH_CARD_STAT_INC(card, rx_sg_alloc_page);
                }
        }
        list_del_init(&entry->list);
@@ -2625,12 +2680,12 @@ static int qeth_init_input_buffer(struct qeth_card *card,
                                               ETH_HLEN +
                                               sizeof(struct ipv6hdr));
                if (!buf->rx_skb)
-                       return 1;
+                       return -ENOMEM;
        }
 
        pool_entry = qeth_find_free_buffer_pool_entry(card);
        if (!pool_entry)
-               return 1;
+               return -ENOBUFS;
 
        /*
         * since the buffer is accessed only from the input_tasklet
@@ -2643,7 +2698,7 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
                buf->buffer->element[i].length = PAGE_SIZE;
                buf->buffer->element[i].addr =
-                       virt_to_phys(pool_entry->elements[i]);
+                       page_to_phys(pool_entry->elements[i]);
                if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
                        buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY;
                else
@@ -2675,10 +2730,15 @@ static int qeth_init_qdio_queues(struct qeth_card *card)
        /* inbound queue */
        qdio_reset_buffers(card->qdio.in_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
        memset(&card->rx, 0, sizeof(struct qeth_rx));
+
        qeth_initialize_working_pool_list(card);
        /*give only as many buffers to hardware as we have buffer pool entries*/
-       for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
-               qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+       for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; i++) {
+               rc = qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+               if (rc)
+                       return rc;
+       }
+
        card->qdio.in_q->next_buf_to_init =
                card->qdio.in_buf_pool.buf_count - 1;
        rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
index 2bd9993..78cae61 100644 (file)
@@ -247,8 +247,8 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct qeth_card *card = dev_get_drvdata(dev);
+       unsigned int cnt;
        char *tmp;
-       int cnt, old_cnt;
        int rc = 0;
 
        mutex_lock(&card->conf_mutex);
@@ -257,13 +257,12 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
                goto out;
        }
 
-       old_cnt = card->qdio.in_buf_pool.buf_count;
        cnt = simple_strtoul(buf, &tmp, 10);
        cnt = (cnt < QETH_IN_BUF_COUNT_MIN) ? QETH_IN_BUF_COUNT_MIN :
                ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt);
-       if (old_cnt != cnt) {
-               rc = qeth_realloc_buffer_pool(card, cnt);
-       }
+
+       rc = qeth_resize_buffer_pool(card, cnt);
+
 out:
        mutex_unlock(&card->conf_mutex);
        return rc ? rc : count;
index 9972d96..8fb2937 100644 (file)
@@ -284,6 +284,7 @@ static void qeth_l2_stop_card(struct qeth_card *card)
        if (card->state == CARD_STATE_SOFTSETUP) {
                qeth_clear_ipacmd_list(card);
                qeth_drain_output_queues(card);
+               cancel_delayed_work_sync(&card->buffer_reclaim_work);
                card->state = CARD_STATE_DOWN;
        }
 
index 317d566..82f800d 100644 (file)
@@ -1178,6 +1178,7 @@ static void qeth_l3_stop_card(struct qeth_card *card)
                qeth_l3_clear_ip_htable(card, 1);
                qeth_clear_ipacmd_list(card);
                qeth_drain_output_queues(card);
+               cancel_delayed_work_sync(&card->buffer_reclaim_work);
                card->state = CARD_STATE_DOWN;
        }
 
index 29f2517..a3d1c3b 100644 (file)
@@ -206,12 +206,11 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
                qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
                if (card->ssqd.qdioac2 & CHSC_AC2_SNIFFER_AVAILABLE) {
                        card->options.sniffer = i;
-                       if (card->qdio.init_pool.buf_count !=
-                                       QETH_IN_BUF_COUNT_MAX)
-                               qeth_realloc_buffer_pool(card,
-                                       QETH_IN_BUF_COUNT_MAX);
-               } else
+                       qeth_resize_buffer_pool(card, QETH_IN_BUF_COUNT_MAX);
+               } else {
                        rc = -EPERM;
+               }
+
                break;
        default:
                rc = -EINVAL;
index 2b1e4da..4bfb79f 100644 (file)
@@ -410,7 +410,7 @@ struct fsf_qtcb_bottom_port {
        u8 cb_util;
        u8 a_util;
        u8 res2;
-       u16 temperature;
+       s16 temperature;
        u16 vcc;
        u16 tx_bias;
        u16 tx_power;
index 494b9fe..a711a0d 100644 (file)
@@ -800,7 +800,7 @@ static ZFCP_DEV_ATTR(adapter_diag, b2b_credit, 0400,
        static ZFCP_DEV_ATTR(adapter_diag_sfp, _name, 0400,                    \
                             zfcp_sysfs_adapter_diag_sfp_##_name##_show, NULL)
 
-ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 6, "%hd");
 ZFCP_DEFINE_DIAG_SFP_ATTR(vcc, vcc, 5, "%hu");
 ZFCP_DEFINE_DIAG_SFP_ATTR(tx_bias, tx_bias, 5, "%hu");
 ZFCP_DEFINE_DIAG_SFP_ATTR(tx_power, tx_power, 5, "%hu");
index 9c5f7c9..2b865c6 100644 (file)
@@ -628,6 +628,8 @@ redisc:
        }
 out:
        kref_put(&rdata->kref, fc_rport_destroy);
+       if (!IS_ERR(fp))
+               fc_frame_free(fp);
 }
 
 /**
index e4282bc..f45c22b 100644 (file)
@@ -161,6 +161,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                        unsigned int nr_zones, report_zones_cb cb, void *data)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
+       sector_t capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
        unsigned int nr, i;
        unsigned char *buf;
        size_t offset, buflen = 0;
@@ -171,11 +172,15 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                /* Not a zoned device */
                return -EOPNOTSUPP;
 
+       if (!capacity)
+               /* Device gone or invalid */
+               return -ENODEV;
+
        buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen);
        if (!buf)
                return -ENOMEM;
 
-       while (zone_idx < nr_zones && sector < get_capacity(disk)) {
+       while (zone_idx < nr_zones && sector < capacity) {
                ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
                                sectors_to_logical(sdkp->device, sector), true);
                if (ret)
index 0fbb8fe..e4240e4 100644 (file)
@@ -688,7 +688,7 @@ static const struct block_device_operations sr_bdops =
        .release        = sr_block_release,
        .ioctl          = sr_block_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl          = sr_block_compat_ioctl,
+       .compat_ioctl   = sr_block_compat_ioctl,
 #endif
        .check_events   = sr_block_check_events,
        .revalidate_disk = sr_block_revalidate_disk,
index fb70b8a..20d37ea 100644 (file)
@@ -25,7 +25,7 @@ struct imx_sc_msg_misc_get_soc_id {
                        u32 id;
                } resp;
        } data;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_misc_get_soc_uid {
        struct imx_sc_rpc_msg hdr;
index fd8007e..13def7f 100644 (file)
@@ -149,6 +149,7 @@ struct atmel_qspi {
        struct clk              *qspick;
        struct platform_device  *pdev;
        const struct atmel_qspi_caps *caps;
+       resource_size_t         mmap_size;
        u32                     pending;
        u32                     mr;
        u32                     scr;
@@ -329,6 +330,14 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
        u32 sr, offset;
        int err;
 
+       /*
+        * Check if the address exceeds the MMIO window size. An improvement
+        * would be to add support for regular SPI mode and fall back to it
+        * when the flash memories overrun the controller's memory space.
+        */
+       if (op->addr.val + op->data.nbytes > aq->mmap_size)
+               return -ENOTSUPP;
+
        err = atmel_qspi_set_cfg(aq, op, &offset);
        if (err)
                return err;
@@ -480,6 +489,8 @@ static int atmel_qspi_probe(struct platform_device *pdev)
                goto exit;
        }
 
+       aq->mmap_size = resource_size(res);
+
        /* Get the peripheral clock */
        aq->pclk = devm_clk_get(&pdev->dev, "pclk");
        if (IS_ERR(aq->pclk))
index 7327309..6c23530 100644 (file)
@@ -366,7 +366,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)
                        goto out_disable_clk;
 
                rate = clk_get_rate(pll_clk);
-               clk_disable_unprepare(pll_clk);
                if (!rate) {
                        ret = -EINVAL;
                        goto out_disable_pll_clk;
index 7e2292c..e9e2567 100644 (file)
@@ -130,6 +130,7 @@ struct omap2_mcspi {
        int                     fifo_depth;
        bool                    slave_aborted;
        unsigned int            pin_dir:1;
+       size_t                  max_xfer_len;
 };
 
 struct omap2_mcspi_cs {
@@ -974,20 +975,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
  * Note that we currently allow DMA only if we get a channel
  * for both rx and tx. Otherwise we'll do PIO for both rx and tx.
  */
-static int omap2_mcspi_request_dma(struct spi_device *spi)
+static int omap2_mcspi_request_dma(struct omap2_mcspi *mcspi,
+                                  struct omap2_mcspi_dma *mcspi_dma)
 {
-       struct spi_master       *master = spi->master;
-       struct omap2_mcspi      *mcspi;
-       struct omap2_mcspi_dma  *mcspi_dma;
        int ret = 0;
 
-       mcspi = spi_master_get_devdata(master);
-       mcspi_dma = mcspi->dma_channels + spi->chip_select;
-
-       init_completion(&mcspi_dma->dma_rx_completion);
-       init_completion(&mcspi_dma->dma_tx_completion);
-
-       mcspi_dma->dma_rx = dma_request_chan(&master->dev,
+       mcspi_dma->dma_rx = dma_request_chan(mcspi->dev,
                                             mcspi_dma->dma_rx_ch_name);
        if (IS_ERR(mcspi_dma->dma_rx)) {
                ret = PTR_ERR(mcspi_dma->dma_rx);
@@ -995,7 +988,7 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
                goto no_dma;
        }
 
-       mcspi_dma->dma_tx = dma_request_chan(&master->dev,
+       mcspi_dma->dma_tx = dma_request_chan(mcspi->dev,
                                             mcspi_dma->dma_tx_ch_name);
        if (IS_ERR(mcspi_dma->dma_tx)) {
                ret = PTR_ERR(mcspi_dma->dma_tx);
@@ -1004,20 +997,40 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
                mcspi_dma->dma_rx = NULL;
        }
 
+       init_completion(&mcspi_dma->dma_rx_completion);
+       init_completion(&mcspi_dma->dma_tx_completion);
+
 no_dma:
        return ret;
 }
 
+static void omap2_mcspi_release_dma(struct spi_master *master)
+{
+       struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+       struct omap2_mcspi_dma  *mcspi_dma;
+       int i;
+
+       for (i = 0; i < master->num_chipselect; i++) {
+               mcspi_dma = &mcspi->dma_channels[i];
+
+               if (mcspi_dma->dma_rx) {
+                       dma_release_channel(mcspi_dma->dma_rx);
+                       mcspi_dma->dma_rx = NULL;
+               }
+               if (mcspi_dma->dma_tx) {
+                       dma_release_channel(mcspi_dma->dma_tx);
+                       mcspi_dma->dma_tx = NULL;
+               }
+       }
+}
+
 static int omap2_mcspi_setup(struct spi_device *spi)
 {
        int                     ret;
        struct omap2_mcspi      *mcspi = spi_master_get_devdata(spi->master);
        struct omap2_mcspi_regs *ctx = &mcspi->ctx;
-       struct omap2_mcspi_dma  *mcspi_dma;
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
        if (!cs) {
                cs = kzalloc(sizeof *cs, GFP_KERNEL);
                if (!cs)
@@ -1042,13 +1055,6 @@ static int omap2_mcspi_setup(struct spi_device *spi)
                }
        }
 
-       if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) {
-               ret = omap2_mcspi_request_dma(spi);
-               if (ret)
-                       dev_warn(&spi->dev, "not using DMA for McSPI (%d)\n",
-                                ret);
-       }
-
        ret = pm_runtime_get_sync(mcspi->dev);
        if (ret < 0) {
                pm_runtime_put_noidle(mcspi->dev);
@@ -1065,12 +1071,8 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 
 static void omap2_mcspi_cleanup(struct spi_device *spi)
 {
-       struct omap2_mcspi      *mcspi;
-       struct omap2_mcspi_dma  *mcspi_dma;
        struct omap2_mcspi_cs   *cs;
 
-       mcspi = spi_master_get_devdata(spi->master);
-
        if (spi->controller_state) {
                /* Unlink controller state from context save list */
                cs = spi->controller_state;
@@ -1079,19 +1081,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi)
                kfree(cs);
        }
 
-       if (spi->chip_select < spi->master->num_chipselect) {
-               mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
-               if (mcspi_dma->dma_rx) {
-                       dma_release_channel(mcspi_dma->dma_rx);
-                       mcspi_dma->dma_rx = NULL;
-               }
-               if (mcspi_dma->dma_tx) {
-                       dma_release_channel(mcspi_dma->dma_tx);
-                       mcspi_dma->dma_tx = NULL;
-               }
-       }
-
        if (gpio_is_valid(spi->cs_gpio))
                gpio_free(spi->cs_gpio);
 }
@@ -1302,9 +1291,24 @@ static bool omap2_mcspi_can_dma(struct spi_master *master,
        if (spi_controller_is_slave(master))
                return true;
 
+       master->dma_rx = mcspi_dma->dma_rx;
+       master->dma_tx = mcspi_dma->dma_tx;
+
        return (xfer->len >= DMA_MIN_BYTES);
 }
 
+static size_t omap2_mcspi_max_xfer_size(struct spi_device *spi)
+{
+       struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
+       struct omap2_mcspi_dma *mcspi_dma =
+               &mcspi->dma_channels[spi->chip_select];
+
+       if (mcspi->max_xfer_len && mcspi_dma->dma_rx)
+               return mcspi->max_xfer_len;
+
+       return SIZE_MAX;
+}
+
 static int omap2_mcspi_controller_setup(struct omap2_mcspi *mcspi)
 {
        struct spi_master       *master = mcspi->master;
@@ -1373,6 +1377,11 @@ static struct omap2_mcspi_platform_config omap4_pdata = {
        .regs_offset = OMAP4_MCSPI_REG_OFFSET,
 };
 
+static struct omap2_mcspi_platform_config am654_pdata = {
+       .regs_offset = OMAP4_MCSPI_REG_OFFSET,
+       .max_xfer_len = SZ_4K - 1,
+};
+
 static const struct of_device_id omap_mcspi_of_match[] = {
        {
                .compatible = "ti,omap2-mcspi",
@@ -1382,6 +1391,10 @@ static const struct of_device_id omap_mcspi_of_match[] = {
                .compatible = "ti,omap4-mcspi",
                .data = &omap4_pdata,
        },
+       {
+               .compatible = "ti,am654-mcspi",
+               .data = &am654_pdata,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, omap_mcspi_of_match);
@@ -1439,6 +1452,10 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
                mcspi->pin_dir = pdata->pin_dir;
        }
        regs_offset = pdata->regs_offset;
+       if (pdata->max_xfer_len) {
+               mcspi->max_xfer_len = pdata->max_xfer_len;
+               master->max_transfer_size = omap2_mcspi_max_xfer_size;
+       }
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mcspi->base = devm_ioremap_resource(&pdev->dev, r);
@@ -1464,6 +1481,11 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        for (i = 0; i < master->num_chipselect; i++) {
                sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i);
                sprintf(mcspi->dma_channels[i].dma_tx_ch_name, "tx%d", i);
+
+               status = omap2_mcspi_request_dma(mcspi,
+                                                &mcspi->dma_channels[i]);
+               if (status == -EPROBE_DEFER)
+                       goto free_master;
        }
 
        status = platform_get_irq(pdev, 0);
@@ -1501,6 +1523,7 @@ disable_pm:
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 free_master:
+       omap2_mcspi_release_dma(master);
        spi_master_put(master);
        return status;
 }
@@ -1510,6 +1533,8 @@ static int omap2_mcspi_remove(struct platform_device *pdev)
        struct spi_master *master = platform_get_drvdata(pdev);
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
+       omap2_mcspi_release_dma(master);
+
        pm_runtime_dont_use_autosuspend(mcspi->dev);
        pm_runtime_put_sync(mcspi->dev);
        pm_runtime_disable(&pdev->dev);
index 4c7a71f..2e31815 100644 (file)
@@ -70,6 +70,10 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_CAPS_CS_EN_SHIFT                  9
 #define LPSS_CAPS_CS_EN_MASK                   (0xf << LPSS_CAPS_CS_EN_SHIFT)
 
+#define LPSS_PRIV_CLOCK_GATE 0x38
+#define LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK 0x3
+#define LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON 0x3
+
 struct lpss_config {
        /* LPSS offset from drv_data->ioaddr */
        unsigned offset;
@@ -86,6 +90,8 @@ struct lpss_config {
        unsigned cs_sel_shift;
        unsigned cs_sel_mask;
        unsigned cs_num;
+       /* Quirks */
+       unsigned cs_clk_stays_gated : 1;
 };
 
 /* Keep these sorted with enum pxa_ssp_type */
@@ -156,6 +162,7 @@ static const struct lpss_config lpss_platforms[] = {
                .tx_threshold_hi = 56,
                .cs_sel_shift = 8,
                .cs_sel_mask = 3 << 8,
+               .cs_clk_stays_gated = true,
        },
 };
 
@@ -383,6 +390,22 @@ static void lpss_ssp_cs_control(struct spi_device *spi, bool enable)
        else
                value |= LPSS_CS_CONTROL_CS_HIGH;
        __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
+       if (config->cs_clk_stays_gated) {
+               u32 clkgate;
+
+               /*
+                * Changing CS alone when dynamic clock gating is on won't
+                * actually flip CS at that time. This ruins SPI transfers
+                * that specify delays, or have no data. Toggle the clock mode
+                * to force on briefly to poke the CS pin to move.
+                */
+               clkgate = __lpss_ssp_read_priv(drv_data, LPSS_PRIV_CLOCK_GATE);
+               value = (clkgate & ~LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK) |
+                       LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON;
+
+               __lpss_ssp_write_priv(drv_data, LPSS_PRIV_CLOCK_GATE, value);
+               __lpss_ssp_write_priv(drv_data, LPSS_PRIV_CLOCK_GATE, clkgate);
+       }
 }
 
 static void cs_assert(struct spi_device *spi)
index dd3434a..a364b99 100644 (file)
@@ -1217,6 +1217,11 @@ static int spi_qup_suspend(struct device *device)
        struct spi_qup *controller = spi_master_get_devdata(master);
        int ret;
 
+       if (pm_runtime_suspended(device)) {
+               ret = spi_qup_pm_resume_runtime(device);
+               if (ret)
+                       return ret;
+       }
        ret = spi_master_suspend(master);
        if (ret)
                return ret;
@@ -1225,10 +1230,8 @@ static int spi_qup_suspend(struct device *device)
        if (ret)
                return ret;
 
-       if (!pm_runtime_suspended(device)) {
-               clk_disable_unprepare(controller->cclk);
-               clk_disable_unprepare(controller->iclk);
-       }
+       clk_disable_unprepare(controller->cclk);
+       clk_disable_unprepare(controller->iclk);
        return 0;
 }
 
index 60c4de4..7412a30 100644 (file)
@@ -401,9 +401,6 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 
        zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
 
-       /* Dummy generic FIFO entry */
-       zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0);
-
        /* Manually start the generic FIFO command */
        zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
                        zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
index 38b4c78..755221b 100644 (file)
@@ -2639,7 +2639,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                if (ctlr->use_gpio_descriptors) {
                        status = spi_get_gpio_descs(ctlr);
                        if (status)
-                               return status;
+                               goto free_bus_id;
                        /*
                         * A controller using GPIO descriptors always
                         * supports SPI_CS_HIGH if need be.
@@ -2649,7 +2649,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                        /* Legacy code path for GPIOs from DT */
                        status = of_spi_get_gpio_numbers(ctlr);
                        if (status)
-                               return status;
+                               goto free_bus_id;
                }
        }
 
@@ -2657,17 +2657,14 @@ int spi_register_controller(struct spi_controller *ctlr)
         * Even if it's just one always-selected device, there must
         * be at least one chipselect.
         */
-       if (!ctlr->num_chipselect)
-               return -EINVAL;
+       if (!ctlr->num_chipselect) {
+               status = -EINVAL;
+               goto free_bus_id;
+       }
 
        status = device_add(&ctlr->dev);
-       if (status < 0) {
-               /* free bus id */
-               mutex_lock(&board_lock);
-               idr_remove(&spi_master_idr, ctlr->bus_num);
-               mutex_unlock(&board_lock);
-               goto done;
-       }
+       if (status < 0)
+               goto free_bus_id;
        dev_dbg(dev, "registered %s %s\n",
                        spi_controller_is_slave(ctlr) ? "slave" : "master",
                        dev_name(&ctlr->dev));
@@ -2683,11 +2680,7 @@ int spi_register_controller(struct spi_controller *ctlr)
                status = spi_controller_initialize_queue(ctlr);
                if (status) {
                        device_del(&ctlr->dev);
-                       /* free bus id */
-                       mutex_lock(&board_lock);
-                       idr_remove(&spi_master_idr, ctlr->bus_num);
-                       mutex_unlock(&board_lock);
-                       goto done;
+                       goto free_bus_id;
                }
        }
        /* add statistics */
@@ -2702,7 +2695,12 @@ int spi_register_controller(struct spi_controller *ctlr)
        /* Register devices from the device tree and ACPI */
        of_register_spi_devices(ctlr);
        acpi_register_spi_devices(ctlr);
-done:
+       return status;
+
+free_bus_id:
+       mutex_lock(&board_lock);
+       idr_remove(&spi_master_idr, ctlr->bus_num);
+       mutex_unlock(&board_lock);
        return status;
 }
 EXPORT_SYMBOL_GPL(spi_register_controller);
index 1e217e3..2ab6e78 100644 (file)
@@ -396,6 +396,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                else
                        retval = get_user(tmp, (u32 __user *)arg);
                if (retval == 0) {
+                       struct spi_controller *ctlr = spi->controller;
                        u32     save = spi->mode;
 
                        if (tmp & ~SPI_MODE_MASK) {
@@ -403,6 +404,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                                break;
                        }
 
+                       if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods &&
+                           ctlr->cs_gpiods[spi->chip_select])
+                               tmp |= SPI_CS_HIGH;
+
                        tmp |= spi->mode & ~SPI_MODE_MASK;
                        spi->mode = (u16)tmp;
                        retval = spi_setup(spi);
index 97c615a..c988353 100644 (file)
@@ -558,13 +558,13 @@ static int hantro_attach_func(struct hantro_dev *vpu,
                goto err_rel_entity1;
 
        /* Connect the three entities */
-       ret = media_create_pad_link(&func->vdev.entity, 0, &func->proc, 1,
+       ret = media_create_pad_link(&func->vdev.entity, 0, &func->proc, 0,
                                    MEDIA_LNK_FL_IMMUTABLE |
                                    MEDIA_LNK_FL_ENABLED);
        if (ret)
                goto err_rel_entity2;
 
-       ret = media_create_pad_link(&func->proc, 0, &func->sink, 0,
+       ret = media_create_pad_link(&func->proc, 1, &func->sink, 0,
                                    MEDIA_LNK_FL_IMMUTABLE |
                                    MEDIA_LNK_FL_ENABLED);
        if (ret)
index a8b4d0c..032f326 100644 (file)
@@ -51,9 +51,7 @@ static void __speakup_set_selection(struct work_struct *work)
                goto unref;
        }
 
-       console_lock();
        set_selection_kernel(&sel, tty);
-       console_unlock();
 
 unref:
        tty_kref_put(tty);
index 26de676..081d58a 100644 (file)
@@ -93,5 +93,5 @@ Some properties are recognized either by SPI and SDIO versions:
    Must contains 64 hexadecimal digits. Not supported in current version.
 
 WFx driver also supports `mac-address` and `local-mac-address` as described in
-Documentation/devicetree/binding/net/ethernet.txt
+Documentation/devicetree/bindings/net/ethernet.txt
 
index 4e32b64..191f971 100644 (file)
@@ -3,6 +3,6 @@
 config AMDTEE
        tristate "AMD-TEE"
        default m
-       depends on CRYPTO_DEV_SP_PSP
+       depends on CRYPTO_DEV_SP_PSP && CRYPTO_DEV_CCP_DD
        help
          This implements AMD's Trusted Execution Environment (TEE) driver.
index 6370bb5..0026eb6 100644 (file)
@@ -212,6 +212,19 @@ unlock:
        return rc;
 }
 
+static void destroy_session(struct kref *ref)
+{
+       struct amdtee_session *sess = container_of(ref, struct amdtee_session,
+                                                  refcount);
+
+       /* Unload the TA from TEE */
+       handle_unload_ta(sess->ta_handle);
+       mutex_lock(&session_list_mutex);
+       list_del(&sess->list_node);
+       mutex_unlock(&session_list_mutex);
+       kfree(sess);
+}
+
 int amdtee_open_session(struct tee_context *ctx,
                        struct tee_ioctl_open_session_arg *arg,
                        struct tee_param *param)
@@ -236,15 +249,13 @@ int amdtee_open_session(struct tee_context *ctx,
 
        /* Load the TA binary into TEE environment */
        handle_load_ta(ta, ta_size, arg);
-       if (arg->ret == TEEC_SUCCESS) {
-               mutex_lock(&session_list_mutex);
-               sess = alloc_session(ctxdata, arg->session);
-               mutex_unlock(&session_list_mutex);
-       }
-
        if (arg->ret != TEEC_SUCCESS)
                goto out;
 
+       mutex_lock(&session_list_mutex);
+       sess = alloc_session(ctxdata, arg->session);
+       mutex_unlock(&session_list_mutex);
+
        if (!sess) {
                rc = -ENOMEM;
                goto out;
@@ -259,40 +270,29 @@ int amdtee_open_session(struct tee_context *ctx,
 
        if (i >= TEE_NUM_SESSIONS) {
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
+               kref_put(&sess->refcount, destroy_session);
                rc = -ENOMEM;
                goto out;
        }
 
        /* Open session with loaded TA */
        handle_open_session(arg, &session_info, param);
-
-       if (arg->ret == TEEC_SUCCESS) {
-               sess->session_info[i] = session_info;
-               set_session_id(sess->ta_handle, i, &arg->session);
-       } else {
+       if (arg->ret != TEEC_SUCCESS) {
                pr_err("open_session failed %d\n", arg->ret);
                spin_lock(&sess->lock);
                clear_bit(i, sess->sess_mask);
                spin_unlock(&sess->lock);
+               kref_put(&sess->refcount, destroy_session);
+               goto out;
        }
+
+       sess->session_info[i] = session_info;
+       set_session_id(sess->ta_handle, i, &arg->session);
 out:
        free_pages((u64)ta, get_order(ta_size));
        return rc;
 }
 
-static void destroy_session(struct kref *ref)
-{
-       struct amdtee_session *sess = container_of(ref, struct amdtee_session,
-                                                  refcount);
-
-       /* Unload the TA from TEE */
-       handle_unload_ta(sess->ta_handle);
-       mutex_lock(&session_list_mutex);
-       list_del(&sess->list_node);
-       mutex_unlock(&session_list_mutex);
-       kfree(sess);
-}
-
 int amdtee_close_session(struct tee_context *ctx, u32 session)
 {
        struct amdtee_context_data *ctxdata = ctx->data;
index 42345e7..c5f0d93 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <linux/serdev.h>
 #include <linux/slab.h>
+#include <linux/platform_data/x86/apple.h>
 
 static bool is_registered;
 static DEFINE_IDA(ctrl_ida);
@@ -631,6 +632,15 @@ static int acpi_serdev_check_resources(struct serdev_controller *ctrl,
        if (ret)
                return ret;
 
+       /*
+        * Apple machines provide an empty resource template, so on those
+        * machines just look for immediate children with a "baud" property
+        * (from the _DSM method) instead.
+        */
+       if (!lookup.controller_handle && x86_apple_machine &&
+           !acpi_dev_get_property(adev, "baud", ACPI_TYPE_BUFFER, NULL))
+               acpi_get_parent(adev->handle, &lookup.controller_handle);
+
        /* Make sure controller and ResourceSource handle match */
        if (ACPI_HANDLE(ctrl->dev.parent) != lookup.controller_handle)
                return -ENODEV;
index 91e9b07..d330da7 100644 (file)
 
 #include "8250.h"
 
+#define PCI_DEVICE_ID_ACCES_COM_2S             0x1052
+#define PCI_DEVICE_ID_ACCES_COM_4S             0x105d
+#define PCI_DEVICE_ID_ACCES_COM_8S             0x106c
+#define PCI_DEVICE_ID_ACCES_COM232_8           0x10a8
+#define PCI_DEVICE_ID_ACCES_COM_2SM            0x10d2
+#define PCI_DEVICE_ID_ACCES_COM_4SM            0x10db
+#define PCI_DEVICE_ID_ACCES_COM_8SM            0x10ea
+
 #define PCI_DEVICE_ID_COMMTECH_4224PCI335      0x0002
 #define PCI_DEVICE_ID_COMMTECH_4222PCI335      0x0004
 #define PCI_DEVICE_ID_COMMTECH_2324PCI335      0x000a
@@ -677,6 +685,22 @@ static int __maybe_unused exar_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
 
+static const struct exar8250_board acces_com_2x = {
+       .num_ports      = 2,
+       .setup          = pci_xr17c154_setup,
+};
+
+static const struct exar8250_board acces_com_4x = {
+       .num_ports      = 4,
+       .setup          = pci_xr17c154_setup,
+};
+
+static const struct exar8250_board acces_com_8x = {
+       .num_ports      = 8,
+       .setup          = pci_xr17c154_setup,
+};
+
+
 static const struct exar8250_board pbn_fastcom335_2 = {
        .num_ports      = 2,
        .setup          = pci_fastcom335_setup,
@@ -745,6 +769,15 @@ static const struct exar8250_board pbn_exar_XR17V8358 = {
        }
 
 static const struct pci_device_id exar_pci_tbl[] = {
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x),
+       EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x),
+
+
        CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
        CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
        CONNECT_DEVICE(XR17C158, UART_8_232, pbn_connect),
index 91e2805..c31b8f3 100644 (file)
@@ -264,6 +264,7 @@ struct lpuart_port {
        int                     rx_dma_rng_buf_len;
        unsigned int            dma_tx_nents;
        wait_queue_head_t       dma_wait;
+       bool                    id_allocated;
 };
 
 struct lpuart_soc_data {
@@ -2390,6 +2391,8 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic
 OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
 OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
 OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
+EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
+EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);
 
 #define LPUART_CONSOLE (&lpuart_console)
 #define LPUART32_CONSOLE       (&lpuart32_console)
@@ -2420,19 +2423,6 @@ static int lpuart_probe(struct platform_device *pdev)
        if (!sport)
                return -ENOMEM;
 
-       ret = of_alias_get_id(np, "serial");
-       if (ret < 0) {
-               ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "port line is full, add device failed\n");
-                       return ret;
-               }
-       }
-       if (ret >= ARRAY_SIZE(lpuart_ports)) {
-               dev_err(&pdev->dev, "serial%d out of range\n", ret);
-               return -EINVAL;
-       }
-       sport->port.line = ret;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(sport->port.membase))
@@ -2477,9 +2467,25 @@ static int lpuart_probe(struct platform_device *pdev)
                }
        }
 
+       ret = of_alias_get_id(np, "serial");
+       if (ret < 0) {
+               ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "port line is full, add device failed\n");
+                       return ret;
+               }
+               sport->id_allocated = true;
+       }
+       if (ret >= ARRAY_SIZE(lpuart_ports)) {
+               dev_err(&pdev->dev, "serial%d out of range\n", ret);
+               ret = -EINVAL;
+               goto failed_out_of_range;
+       }
+       sport->port.line = ret;
+
        ret = lpuart_enable_clks(sport);
        if (ret)
-               return ret;
+               goto failed_clock_enable;
        sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
 
        lpuart_ports[sport->port.line] = sport;
@@ -2529,6 +2535,10 @@ static int lpuart_probe(struct platform_device *pdev)
 failed_attach_port:
 failed_irq_request:
        lpuart_disable_clks(sport);
+failed_clock_enable:
+failed_out_of_range:
+       if (sport->id_allocated)
+               ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
        return ret;
 }
 
@@ -2538,7 +2548,8 @@ static int lpuart_remove(struct platform_device *pdev)
 
        uart_remove_one_port(&lpuart_reg, &sport->port);
 
-       ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
+       if (sport->id_allocated)
+               ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
 
        lpuart_disable_clks(sport);
 
index c12a125..4e9a590 100644 (file)
@@ -851,7 +851,7 @@ static int mvebu_uart_probe(struct platform_device *pdev)
 
        port->membase = devm_ioremap_resource(&pdev->dev, reg);
        if (IS_ERR(port->membase))
-               return -PTR_ERR(port->membase);
+               return PTR_ERR(port->membase);
 
        mvuart = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_uart),
                              GFP_KERNEL);
index 0c50d74..d7d2e4b 100644 (file)
@@ -181,7 +181,7 @@ int set_selection_user(const struct tiocl_selection __user *sel,
        return set_selection_kernel(&v, tty);
 }
 
-int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
+static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
 {
        struct vc_data *vc = vc_cons[fg_console].d;
        int new_sel_start, new_sel_end, spc;
@@ -214,7 +214,6 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (ps > pe)    /* make sel_start <= sel_end */
                swap(ps, pe);
 
-       mutex_lock(&sel_lock);
        if (sel_cons != vc_cons[fg_console].d) {
                clear_selection();
                sel_cons = vc_cons[fg_console].d;
@@ -260,10 +259,9 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                        break;
                case TIOCL_SELPOINTER:
                        highlight_pointer(pe);
-                       goto unlock;
+                       return 0;
                default:
-                       ret = -EINVAL;
-                       goto unlock;
+                       return -EINVAL;
        }
 
        /* remove the pointer */
@@ -285,7 +283,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        else if (new_sel_start == sel_start)
        {
                if (new_sel_end == sel_end)     /* no action required */
-                       goto unlock;
+                       return 0;
                else if (new_sel_end > sel_end) /* extend to right */
                        highlight(sel_end + 2, new_sel_end);
                else                            /* contract from right */
@@ -313,8 +311,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (!bp) {
                printk(KERN_WARNING "selection: kmalloc() failed\n");
                clear_selection();
-               ret = -ENOMEM;
-               goto unlock;
+               return -ENOMEM;
        }
        kfree(sel_buffer);
        sel_buffer = bp;
@@ -339,8 +336,20 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                }
        }
        sel_buffer_lth = bp - sel_buffer;
-unlock:
+
+       return ret;
+}
+
+int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
+{
+       int ret;
+
+       mutex_lock(&sel_lock);
+       console_lock();
+       ret = __set_selection_kernel(v, tty);
+       console_unlock();
        mutex_unlock(&sel_lock);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(set_selection_kernel);
index 0cfbb71..15d2769 100644 (file)
@@ -3046,10 +3046,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        switch (type)
        {
                case TIOCL_SETSEL:
-                       console_lock();
                        ret = set_selection_user((struct tiocl_selection
                                                 __user *)(p+1), tty);
-                       console_unlock();
                        break;
                case TIOCL_PASTESEL:
                        ret = paste_selection(tty);
index 736b0c6..3574dbb 100644 (file)
@@ -2550,7 +2550,7 @@ found:
        /* Update ring only if removed request is on pending_req_list list */
        if (req_on_hw_ring) {
                link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma +
-                                             (priv_req->start_trb * TRB_SIZE));
+                       ((priv_req->end_trb + 1) * TRB_SIZE));
                link_trb->control = (link_trb->control & TRB_CYCLE) |
                                    TRB_TYPE(TRB_LINK) | TRB_CHAIN;
 
@@ -2595,11 +2595,21 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
 {
        struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
        struct usb_request *request;
+       struct cdns3_request *priv_req;
+       struct cdns3_trb *trb = NULL;
        int ret;
        int val;
 
        trace_cdns3_halt(priv_ep, 0, 0);
 
+       request = cdns3_next_request(&priv_ep->pending_req_list);
+       if (request) {
+               priv_req = to_cdns3_request(request);
+               trb = priv_req->trb;
+               if (trb)
+                       trb->control = trb->control ^ TRB_CYCLE;
+       }
+
        writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
 
        /* wait for EPRST cleared */
@@ -2610,10 +2620,11 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
 
        priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING);
 
-       request = cdns3_next_request(&priv_ep->pending_req_list);
-
-       if (request)
+       if (request) {
+               if (trb)
+                       trb->control = trb->control ^ TRB_CYCLE;
                cdns3_rearm_transfer(priv_ep, 1);
+       }
 
        cdns3_start_all_request(priv_dev, priv_ep);
        return ret;
index 1d212f8..54cd8ef 100644 (file)
@@ -988,13 +988,17 @@ int usb_remove_device(struct usb_device *udev)
 {
        struct usb_hub *hub;
        struct usb_interface *intf;
+       int ret;
 
        if (!udev->parent)      /* Can't remove a root hub */
                return -EINVAL;
        hub = usb_hub_to_struct_hub(udev->parent);
        intf = to_usb_interface(hub->intfdev);
 
-       usb_autopm_get_interface(intf);
+       ret = usb_autopm_get_interface(intf);
+       if (ret < 0)
+               return ret;
+
        set_bit(udev->portnum, hub->removed_bits);
        hub_port_logical_disconnect(hub, udev->portnum);
        usb_autopm_put_interface(intf);
@@ -1866,7 +1870,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
        if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) {
                hub->quirk_disable_autosuspend = 1;
-               usb_autopm_get_interface(intf);
+               usb_autopm_get_interface_no_resume(intf);
        }
 
        if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
index bbbb35f..235a7c6 100644 (file)
@@ -213,7 +213,10 @@ static int usb_port_runtime_resume(struct device *dev)
        if (!port_dev->is_superspeed && peer)
                pm_runtime_get_sync(&peer->dev);
 
-       usb_autopm_get_interface(intf);
+       retval = usb_autopm_get_interface(intf);
+       if (retval < 0)
+               return retval;
+
        retval = usb_hub_set_port_power(hdev, hub, port1, true);
        msleep(hub_power_on_good_delay(hub));
        if (udev && !retval) {
@@ -266,7 +269,10 @@ static int usb_port_runtime_suspend(struct device *dev)
        if (usb_port_block_power_off)
                return -EBUSY;
 
-       usb_autopm_get_interface(intf);
+       retval = usb_autopm_get_interface(intf);
+       if (retval < 0)
+               return retval;
+
        retval = usb_hub_set_port_power(hdev, hub, port1, false);
        usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
        if (!port_dev->is_superspeed)
index 2b24336..2dac3e7 100644 (file)
@@ -231,6 +231,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Logitech PTZ Pro Camera */
        { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT },
 
+       /* Logitech Screen Share */
+       { USB_DEVICE(0x046d, 0x086c), .driver_info = USB_QUIRK_NO_LPM },
+
        /* Logitech Quickcam Fusion */
        { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
index 1b7d2f9..1e00bf2 100644 (file)
@@ -1071,7 +1071,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
                unsigned int rem = length % maxp;
                unsigned chain = true;
 
-               if (sg_is_last(s))
+               /*
+                * IOMMU driver is coalescing the list of sgs which shares a
+                * page boundary into one and giving it to USB driver. With
+                * this the number of sgs mapped is not equal to the number of
+                * sgs passed. So mark the chain bit to false if it isthe last
+                * mapped sg.
+                */
+               if (i == remaining - 1)
                        chain = false;
 
                if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
index 10c9e7f..29fe577 100644 (file)
@@ -424,10 +424,6 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
                return err;
        }
 
-       hub->vdd = devm_regulator_get(dev, "vdd");
-       if (IS_ERR(hub->vdd))
-               return PTR_ERR(hub->vdd);
-
        if (of_property_read_u16_array(np, "vendor-id", &hub->vendor_id, 1))
                hub->vendor_id = USB251XB_DEF_VENDOR_ID;
 
@@ -640,6 +636,13 @@ static int usb251xb_get_ofdata(struct usb251xb *hub,
 }
 #endif /* CONFIG_OF */
 
+static void usb251xb_regulator_disable_action(void *data)
+{
+       struct usb251xb *hub = data;
+
+       regulator_disable(hub->vdd);
+}
+
 static int usb251xb_probe(struct usb251xb *hub)
 {
        struct device *dev = hub->dev;
@@ -676,10 +679,19 @@ static int usb251xb_probe(struct usb251xb *hub)
        if (err)
                return err;
 
+       hub->vdd = devm_regulator_get(dev, "vdd");
+       if (IS_ERR(hub->vdd))
+               return PTR_ERR(hub->vdd);
+
        err = regulator_enable(hub->vdd);
        if (err)
                return err;
 
+       err = devm_add_action_or_reset(dev,
+                                      usb251xb_regulator_disable_action, hub);
+       if (err)
+               return err;
+
        err = usb251xb_connect(hub);
        if (err) {
                dev_err(dev, "Failed to connect hub (%d)\n", err);
index 1cd9b63..1880f3e 100644 (file)
@@ -1258,6 +1258,12 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
                USB_SC_RBC, USB_PR_BULK, NULL,
                0 ),
 
+UNUSUAL_DEV(0x090c, 0x1000, 0x1100, 0x1100,
+               "Samsung",
+               "Flash Drive FIT",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64),
+
 /* aeb */
 UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
                "Feiya",
index e158159..18e205e 100644 (file)
@@ -1414,10 +1414,6 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 
 static struct socket *get_raw_socket(int fd)
 {
-       struct {
-               struct sockaddr_ll sa;
-               char  buf[MAX_ADDR_LEN];
-       } uaddr;
        int r;
        struct socket *sock = sockfd_lookup(fd, &r);
 
@@ -1430,11 +1426,7 @@ static struct socket *get_raw_socket(int fd)
                goto err;
        }
 
-       r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, 0);
-       if (r < 0)
-               goto err;
-
-       if (uaddr.sa.sll_family != AF_PACKET) {
+       if (sock->sk->sk_family != AF_PACKET) {
                r = -EPFNOSUPPORT;
                goto err;
        }
index 403707a..0093bbd 100644 (file)
@@ -456,6 +456,13 @@ config BACKLIGHT_RAVE_SP
        help
          Support for backlight control on RAVE SP device.
 
+config BACKLIGHT_LED
+       tristate "Generic LED based Backlight Driver"
+       depends on LEDS_CLASS && OF
+       help
+         If you have a LCD backlight adjustable by LED class driver, say Y
+         to enable this driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endmenu
index 6f87770..0c1a152 100644 (file)
@@ -57,3 +57,4 @@ obj-$(CONFIG_BACKLIGHT_TPS65217)      += tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)         += wm831x_bl.o
 obj-$(CONFIG_BACKLIGHT_ARCXCNN)        += arcxcnn_bl.o
 obj-$(CONFIG_BACKLIGHT_RAVE_SP)                += rave-sp-backlight.o
+obj-$(CONFIG_BACKLIGHT_LED)            += led_bl.o
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
new file mode 100644 (file)
index 0000000..3f66549
--- /dev/null
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015-2019 Texas Instruments Incorporated -  http://www.ti.com/
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * Based on pwm_bl.c
+ */
+
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+struct led_bl_data {
+       struct device           *dev;
+       struct backlight_device *bl_dev;
+       struct led_classdev     **leds;
+       bool                    enabled;
+       int                     nb_leds;
+       unsigned int            *levels;
+       unsigned int            default_brightness;
+       unsigned int            max_brightness;
+};
+
+static void led_bl_set_brightness(struct led_bl_data *priv, int level)
+{
+       int i;
+       int bkl_brightness;
+
+       if (priv->levels)
+               bkl_brightness = priv->levels[level];
+       else
+               bkl_brightness = level;
+
+       for (i = 0; i < priv->nb_leds; i++)
+               led_set_brightness(priv->leds[i], bkl_brightness);
+
+       priv->enabled = true;
+}
+
+static void led_bl_power_off(struct led_bl_data *priv)
+{
+       int i;
+
+       if (!priv->enabled)
+               return;
+
+       for (i = 0; i < priv->nb_leds; i++)
+               led_set_brightness(priv->leds[i], LED_OFF);
+
+       priv->enabled = false;
+}
+
+static int led_bl_update_status(struct backlight_device *bl)
+{
+       struct led_bl_data *priv = bl_get_data(bl);
+       int brightness = bl->props.brightness;
+
+       if (bl->props.power != FB_BLANK_UNBLANK ||
+           bl->props.fb_blank != FB_BLANK_UNBLANK ||
+           bl->props.state & BL_CORE_FBBLANK)
+               brightness = 0;
+
+       if (brightness > 0)
+               led_bl_set_brightness(priv, brightness);
+       else
+               led_bl_power_off(priv);
+
+       return 0;
+}
+
+static const struct backlight_ops led_bl_ops = {
+       .update_status  = led_bl_update_status,
+};
+
+static int led_bl_get_leds(struct device *dev,
+                          struct led_bl_data *priv)
+{
+       int i, nb_leds, ret;
+       struct device_node *node = dev->of_node;
+       struct led_classdev **leds;
+       unsigned int max_brightness;
+       unsigned int default_brightness;
+
+       ret = of_count_phandle_with_args(node, "leds", NULL);
+       if (ret < 0) {
+               dev_err(dev, "Unable to get led count\n");
+               return -EINVAL;
+       }
+
+       nb_leds = ret;
+       if (nb_leds < 1) {
+               dev_err(dev, "At least one LED must be specified!\n");
+               return -EINVAL;
+       }
+
+       leds = devm_kzalloc(dev, sizeof(struct led_classdev *) * nb_leds,
+                           GFP_KERNEL);
+       if (!leds)
+               return -ENOMEM;
+
+       for (i = 0; i < nb_leds; i++) {
+               leds[i] = devm_of_led_get(dev, i);
+               if (IS_ERR(leds[i]))
+                       return PTR_ERR(leds[i]);
+       }
+
+       /* check that the LEDs all have the same brightness range */
+       max_brightness = leds[0]->max_brightness;
+       for (i = 1; i < nb_leds; i++) {
+               if (max_brightness != leds[i]->max_brightness) {
+                       dev_err(dev, "LEDs must have identical ranges\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* get the default brightness from the first LED from the list */
+       default_brightness = leds[0]->brightness;
+
+       priv->nb_leds = nb_leds;
+       priv->leds = leds;
+       priv->max_brightness = max_brightness;
+       priv->default_brightness = default_brightness;
+
+       return 0;
+}
+
+static int led_bl_parse_levels(struct device *dev,
+                          struct led_bl_data *priv)
+{
+       struct device_node *node = dev->of_node;
+       int num_levels;
+       u32 value;
+       int ret;
+
+       if (!node)
+               return -ENODEV;
+
+       num_levels = of_property_count_u32_elems(node, "brightness-levels");
+       if (num_levels > 1) {
+               int i;
+               unsigned int db;
+               u32 *levels = NULL;
+
+               levels = devm_kzalloc(dev, sizeof(u32) * num_levels,
+                                     GFP_KERNEL);
+               if (!levels)
+                       return -ENOMEM;
+
+               ret = of_property_read_u32_array(node, "brightness-levels",
+                                               levels,
+                                               num_levels);
+               if (ret < 0)
+                       return ret;
+
+               /*
+                * Try to map actual LED brightness to backlight brightness
+                * level
+                */
+               db = priv->default_brightness;
+               for (i = 0 ; i < num_levels; i++) {
+                       if ((i && db > levels[i-1]) && db <= levels[i])
+                               break;
+               }
+               priv->default_brightness = i;
+               priv->max_brightness = num_levels - 1;
+               priv->levels = levels;
+       } else if (num_levels >= 0)
+               dev_warn(dev, "Not enough levels defined\n");
+
+       ret = of_property_read_u32(node, "default-brightness-level", &value);
+       if (!ret && value <= priv->max_brightness)
+               priv->default_brightness = value;
+       else if (!ret  && value > priv->max_brightness)
+               dev_warn(dev, "Invalid default brightness. Ignoring it\n");
+
+       return 0;
+}
+
+static int led_bl_probe(struct platform_device *pdev)
+{
+       struct backlight_properties props;
+       struct led_bl_data *priv;
+       int ret, i;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, priv);
+
+       priv->dev = &pdev->dev;
+
+       ret = led_bl_get_leds(&pdev->dev, priv);
+       if (ret)
+               return ret;
+
+       ret = led_bl_parse_levels(&pdev->dev, priv);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to parse DT data\n");
+               return ret;
+       }
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = priv->max_brightness;
+       props.brightness = priv->default_brightness;
+       props.power = (priv->default_brightness > 0) ? FB_BLANK_POWERDOWN :
+                     FB_BLANK_UNBLANK;
+       priv->bl_dev = backlight_device_register(dev_name(&pdev->dev),
+                       &pdev->dev, priv, &led_bl_ops, &props);
+       if (IS_ERR(priv->bl_dev)) {
+               dev_err(&pdev->dev, "Failed to register backlight\n");
+               return PTR_ERR(priv->bl_dev);
+       }
+
+       for (i = 0; i < priv->nb_leds; i++)
+               led_sysfs_disable(priv->leds[i]);
+
+       backlight_update_status(priv->bl_dev);
+
+       return 0;
+}
+
+static int led_bl_remove(struct platform_device *pdev)
+{
+       struct led_bl_data *priv = platform_get_drvdata(pdev);
+       struct backlight_device *bl = priv->bl_dev;
+       int i;
+
+       backlight_device_unregister(bl);
+
+       led_bl_power_off(priv);
+       for (i = 0; i < priv->nb_leds; i++)
+               led_sysfs_enable(priv->leds[i]);
+
+       return 0;
+}
+
+static const struct of_device_id led_bl_of_match[] = {
+       { .compatible = "led-backlight" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, led_bl_of_match);
+
+static struct platform_driver led_bl_driver = {
+       .driver         = {
+               .name           = "led-backlight",
+               .of_match_table = of_match_ptr(led_bl_of_match),
+       },
+       .probe          = led_bl_probe,
+       .remove         = led_bl_remove,
+};
+
+module_platform_driver(led_bl_driver);
+
+MODULE_DESCRIPTION("LED based Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:led-backlight");
index de7b838..998b0de 100644 (file)
@@ -1316,6 +1316,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
 static int vgacon_resize(struct vc_data *c, unsigned int width,
                         unsigned int height, unsigned int user)
 {
+       if ((width << 1) * height > vga_vram_size)
+               return -EINVAL;
+
        if (width % 2 || width > screen_info.orig_video_cols ||
            height > (screen_info.orig_video_lines * vga_default_font_height)/
            c->vc_font.height)
index 7bfe365..341458f 100644 (file)
@@ -959,8 +959,8 @@ out_iput:
        iput(vb->vb_dev_info.inode);
 out_kern_unmount:
        kern_unmount(balloon_mnt);
-#endif
 out_del_vqs:
+#endif
        vdev->config->del_vqs(vdev);
 out_free_vb:
        kfree(vb);
index 867c7eb..58b96ba 100644 (file)
@@ -2203,10 +2203,10 @@ void vring_del_virtqueue(struct virtqueue *_vq)
                                         vq->split.queue_size_in_bytes,
                                         vq->split.vring.desc,
                                         vq->split.queue_dma_addr);
-
-                       kfree(vq->split.desc_state);
                }
        }
+       if (!vq->packed_ring)
+               kfree(vq->split.desc_state);
        list_del(&_vq->list);
        kfree(vq);
 }
index b069349..3065dd6 100644 (file)
@@ -54,6 +54,13 @@ module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+#define WDAT_DEFAULT_TIMEOUT   30
+
+static int timeout = WDAT_DEFAULT_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+                __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")");
+
 static int wdat_wdt_read(struct wdat_wdt *wdat,
         const struct wdat_instruction *instr, u32 *value)
 {
@@ -389,7 +396,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
 
                memset(&r, 0, sizeof(r));
                r.start = gas->address;
-               r.end = r.start + gas->access_width - 1;
+               r.end = r.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
                if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
                        r.flags = IORESOURCE_MEM;
                } else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
@@ -438,6 +445,22 @@ static int wdat_wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, wdat);
 
+       /*
+        * Set initial timeout so that userspace has time to configure the
+        * watchdog properly after it has opened the device. In some cases
+        * the BIOS default is too short and causes immediate reboot.
+        */
+       if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
+           timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
+               dev_warn(dev, "Invalid timeout %d given, using %d\n",
+                        timeout, WDAT_DEFAULT_TIMEOUT);
+               timeout = WDAT_DEFAULT_TIMEOUT;
+       }
+
+       ret = wdat_wdt_set_timeout(&wdat->wdd, timeout);
+       if (ret)
+               return ret;
+
        watchdog_set_nowayout(&wdat->wdd, nowayout);
        return devm_watchdog_register_device(dev, &wdat->wdd);
 }
index ce1077e..7c95516 100644 (file)
@@ -52,7 +52,7 @@ struct xen_pcibk_dev_data {
        unsigned int ack_intr:1; /* .. and ACK-ing */
        unsigned long handled;
        unsigned int irq; /* Saved in case device transitions to MSI/MSI-X */
-       char irq_name[0]; /* xen-pcibk[000:04:00.0] */
+       char irq_name[]; /* xen-pcibk[000:04:00.0] */
 };
 
 /* Used by XenBus and xen_pcibk_ops.c */
index d239fc3..eb5151f 100644 (file)
@@ -313,6 +313,8 @@ static int process_msg(void)
                        req->msg.type = state.msg.type;
                        req->msg.len = state.msg.len;
                        req->body = state.body;
+                       /* write body, then update state */
+                       virt_wmb();
                        req->state = xb_req_state_got_reply;
                        req->cb(req);
                } else
@@ -395,6 +397,8 @@ static int process_writes(void)
        if (state.req->state == xb_req_state_aborted)
                kfree(state.req);
        else {
+               /* write err, then update state */
+               virt_wmb();
                state.req->state = xb_req_state_got_reply;
                wake_up(&state.req->wq);
        }
index 66975da..8c4d05b 100644 (file)
@@ -239,9 +239,9 @@ int xenbus_dev_probe(struct device *_dev)
                goto fail;
        }
 
-       spin_lock(&dev->reclaim_lock);
+       down(&dev->reclaim_sem);
        err = drv->probe(dev, id);
-       spin_unlock(&dev->reclaim_lock);
+       up(&dev->reclaim_sem);
        if (err)
                goto fail_put;
 
@@ -271,9 +271,9 @@ int xenbus_dev_remove(struct device *_dev)
        free_otherend_watch(dev);
 
        if (drv->remove) {
-               spin_lock(&dev->reclaim_lock);
+               down(&dev->reclaim_sem);
                drv->remove(dev);
-               spin_unlock(&dev->reclaim_lock);
+               up(&dev->reclaim_sem);
        }
 
        module_put(drv->driver.owner);
@@ -473,7 +473,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
                goto fail;
 
        dev_set_name(&xendev->dev, "%s", devname);
-       spin_lock_init(&xendev->reclaim_lock);
+       sema_init(&xendev->reclaim_sem, 1);
 
        /* Register with generic device framework. */
        err = device_register(&xendev->dev);
index 791f6fe..9b2fbe6 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/mm.h>
 #include <linux/notifier.h>
 #include <linux/export.h>
+#include <linux/semaphore.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -257,10 +258,10 @@ static int backend_reclaim_memory(struct device *dev, void *data)
        drv = to_xenbus_driver(dev->driver);
        if (drv && drv->reclaim_memory) {
                xdev = to_xenbus_device(dev);
-               if (!spin_trylock(&xdev->reclaim_lock))
+               if (down_trylock(&xdev->reclaim_sem))
                        return 0;
                drv->reclaim_memory(xdev);
-               spin_unlock(&xdev->reclaim_lock);
+               up(&xdev->reclaim_sem);
        }
        return 0;
 }
index ddc18da..3a06eb6 100644 (file)
@@ -191,8 +191,11 @@ static bool xenbus_ok(void)
 
 static bool test_reply(struct xb_req_data *req)
 {
-       if (req->state == xb_req_state_got_reply || !xenbus_ok())
+       if (req->state == xb_req_state_got_reply || !xenbus_ok()) {
+               /* read req->state before all other fields */
+               virt_rmb();
                return true;
+       }
 
        /* Make sure to reread req->state each time. */
        barrier();
@@ -202,7 +205,7 @@ static bool test_reply(struct xb_req_data *req)
 
 static void *read_reply(struct xb_req_data *req)
 {
-       while (req->state != xb_req_state_got_reply) {
+       do {
                wait_event(req->wq, test_reply(req));
 
                if (!xenbus_ok())
@@ -216,7 +219,7 @@ static void *read_reply(struct xb_req_data *req)
                if (req->err)
                        return ERR_PTR(req->err);
 
-       }
+       } while (req->state != xb_req_state_got_reply);
 
        return req->body;
 }
index df415c0..de1ae0b 100644 (file)
@@ -19,7 +19,7 @@
 void afs_put_addrlist(struct afs_addr_list *alist)
 {
        if (alist && refcount_dec_and_test(&alist->usage))
-               call_rcu(&alist->rcu, (rcu_callback_t)kfree);
+               kfree_rcu(alist, rcu);
 }
 
 /*
index 1d81fc4..35f951a 100644 (file)
@@ -81,7 +81,7 @@ enum afs_call_state {
  * List of server addresses.
  */
 struct afs_addr_list {
-       struct rcu_head         rcu;            /* Must be first */
+       struct rcu_head         rcu;
        refcount_t              usage;
        u32                     version;        /* Version */
        unsigned char           max_addrs;
index 1ccb3f8..27076eb 100644 (file)
@@ -7783,6 +7783,7 @@ static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode,
 {
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
        struct btrfs_io_bio *orig_io_bio = btrfs_io_bio(dip->orig_bio);
+       u16 csum_size;
        blk_status_t ret;
 
        /*
@@ -7802,7 +7803,8 @@ static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode,
 
        file_offset -= dip->logical_offset;
        file_offset >>= inode->i_sb->s_blocksize_bits;
-       io_bio->csum = (u8 *)(((u32 *)orig_io_bio->csum) + file_offset);
+       csum_size = btrfs_super_csum_size(btrfs_sb(inode->i_sb)->super_copy);
+       io_bio->csum = orig_io_bio->csum + csum_size * file_offset;
 
        return 0;
 }
index 606f26d..cc3ada1 100644 (file)
@@ -324,6 +324,8 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
        if (full_path == NULL)
                goto cdda_exit;
 
+       convert_delimiter(full_path, '\\');
+
        cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
 
        if (!cifs_sb_master_tlink(cifs_sb)) {
index 46ebaf3..fa77fe5 100644 (file)
@@ -530,6 +530,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
 
        if (tcon->seal)
                seq_puts(s, ",seal");
+       else if (tcon->ses->server->ignore_signature)
+               seq_puts(s, ",signloosely");
        if (tcon->nocase)
                seq_puts(s, ",nocase");
        if (tcon->local_lease)
index de82cfa..0d95636 100644 (file)
@@ -1281,6 +1281,7 @@ struct cifs_fid {
        __u64 volatile_fid;     /* volatile file id for smb2 */
        __u8 lease_key[SMB2_LEASE_KEY_SIZE];    /* lease key for smb2 */
        __u8 create_guid[16];
+       __u32 access;
        struct cifs_pending_open *pending_open;
        unsigned int epoch;
 #ifdef CONFIG_CIFS_DEBUG2
@@ -1741,6 +1742,12 @@ static inline bool is_retryable_error(int error)
        return false;
 }
 
+
+/* cifs_get_writable_file() flags */
+#define FIND_WR_ANY         0
+#define FIND_WR_FSUID_ONLY  1
+#define FIND_WR_WITH_DELETE 2
+
 #define   MID_FREE 0
 #define   MID_REQUEST_ALLOCATED 1
 #define   MID_REQUEST_SUBMITTED 2
index 89eaaf4..e5cb681 100644 (file)
@@ -134,11 +134,12 @@ extern bool backup_cred(struct cifs_sb_info *);
 extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
 extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
                            unsigned int bytes_written);
-extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool);
+extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
 extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
-                                 bool fsuid_only,
+                                 int flags,
                                  struct cifsFileInfo **ret_file);
 extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                                 int flags,
                                  struct cifsFileInfo **ret_file);
 extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
 extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
index 3c89569..6f6fb36 100644 (file)
@@ -1492,6 +1492,7 @@ openRetry:
        *oplock = rsp->OplockLevel;
        /* cifs fid stays in le */
        oparms->fid->netfid = rsp->Fid;
+       oparms->fid->access = desired_access;
 
        /* Let caller know file was created so we can set the mode. */
        /* Do we care about the CreateAction in any other cases? */
@@ -2115,7 +2116,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
                wdata2->tailsz = tailsz;
                wdata2->bytes = cur_len;
 
-               rc = cifs_get_writable_file(CIFS_I(inode), false,
+               rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY,
                                            &wdata2->cfile);
                if (!wdata2->cfile) {
                        cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n",
index 0ef0994..36e7b2f 100644 (file)
@@ -555,7 +555,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
                if (server->ops->close)
                        server->ops->close(xid, tcon, &fid);
                cifs_del_pending_open(&open);
-               fput(file);
                rc = -ENOMEM;
        }
 
index bc9516a..3b942ec 100644 (file)
@@ -1958,7 +1958,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
 
 /* Return -EBADF if no handle is found and general rc otherwise */
 int
-cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
+cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
                       struct cifsFileInfo **ret_file)
 {
        struct cifsFileInfo *open_file, *inv_file = NULL;
@@ -1966,7 +1966,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
        bool any_available = false;
        int rc = -EBADF;
        unsigned int refind = 0;
-
+       bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
+       bool with_delete = flags & FIND_WR_WITH_DELETE;
        *ret_file = NULL;
 
        /*
@@ -1998,6 +1999,8 @@ refind_writable:
                        continue;
                if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
                        continue;
+               if (with_delete && !(open_file->fid.access & DELETE))
+                       continue;
                if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
                        if (!open_file->invalidHandle) {
                                /* found a good writable file */
@@ -2045,12 +2048,12 @@ refind_writable:
 }
 
 struct cifsFileInfo *
-find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only)
+find_writable_file(struct cifsInodeInfo *cifs_inode, int flags)
 {
        struct cifsFileInfo *cfile;
        int rc;
 
-       rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile);
+       rc = cifs_get_writable_file(cifs_inode, flags, &cfile);
        if (rc)
                cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc);
 
@@ -2059,6 +2062,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only)
 
 int
 cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
+                      int flags,
                       struct cifsFileInfo **ret_file)
 {
        struct list_head *tmp;
@@ -2085,7 +2089,7 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
                kfree(full_path);
                cinode = CIFS_I(d_inode(cfile->dentry));
                spin_unlock(&tcon->open_file_lock);
-               return cifs_get_writable_file(cinode, 0, ret_file);
+               return cifs_get_writable_file(cinode, flags, ret_file);
        }
 
        spin_unlock(&tcon->open_file_lock);
@@ -2162,7 +2166,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
        if (mapping->host->i_size - offset < (loff_t)to)
                to = (unsigned)(mapping->host->i_size - offset);
 
-       rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file);
+       rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY,
+                                   &open_file);
        if (!rc) {
                bytes_written = cifs_write(open_file, open_file->pid,
                                           write_data, to - from, &offset);
@@ -2355,7 +2360,7 @@ retry:
                if (cfile)
                        cifsFileInfo_put(cfile);
 
-               rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile);
+               rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
 
                /* in case of an error store it to return later */
                if (rc)
index b5e6635..1e8a4b1 100644 (file)
@@ -653,8 +653,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
                 */
                if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
                    !info->DeletePending) {
-                       cifs_dbg(1, "bogus file nlink value %u\n",
-                               fattr->cf_nlink);
+                       cifs_dbg(VFS, "bogus file nlink value %u\n",
+                                fattr->cf_nlink);
                        fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
                }
        }
@@ -2073,6 +2073,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
        struct inode *inode = d_inode(dentry);
        struct super_block *sb = dentry->d_sb;
        char *full_path = NULL;
+       int count = 0;
 
        if (inode == NULL)
                return -ENOENT;
@@ -2094,15 +2095,18 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
                 full_path, inode, inode->i_count.counter,
                 dentry, cifs_get_time(dentry), jiffies);
 
+again:
        if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
                rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
        else
                rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
                                         xid, NULL);
-
+       if (rc == -EAGAIN && count++ < 10)
+               goto again;
 out:
        kfree(full_path);
        free_xid(xid);
+
        return rc;
 }
 
@@ -2278,7 +2282,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
         * writebehind data than the SMB timeout for the SetPathInfo
         * request would allow
         */
-       open_file = find_writable_file(cifsInode, true);
+       open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                tcon = tlink_tcon(open_file->tlink);
                server = tcon->ses->server;
@@ -2428,7 +2432,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
                args->ctime = NO_CHANGE_64;
 
        args->device = 0;
-       open_file = find_writable_file(cifsInode, true);
+       open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                u16 nfid = open_file->fid.netfid;
                u32 npid = open_file->pid;
@@ -2531,7 +2535,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        rc = 0;
 
        if (attrs->ia_valid & ATTR_MTIME) {
-               rc = cifs_get_writable_file(cifsInode, false, &wfile);
+               rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile);
                if (!rc) {
                        tcon = tlink_tcon(wfile->tlink);
                        rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
index eb994e3..b130efa 100644 (file)
@@ -766,7 +766,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        struct cifs_tcon *tcon;
 
        /* if the file is already open for write, just use that fileid */
-       open_file = find_writable_file(cinode, true);
+       open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
        if (open_file) {
                fid.netfid = open_file->fid.netfid;
                netpid = open_file->pid;
index 1cf2075..a8c301a 100644 (file)
@@ -521,7 +521,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
        cifs_i = CIFS_I(inode);
        dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
        data.Attributes = cpu_to_le32(dosattrs);
-       cifs_get_writable_path(tcon, name, &cfile);
+       cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
        tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
                                 FILE_WRITE_ATTRIBUTES, FILE_CREATE,
                                 CREATE_NOT_FILE, ACL_NO_MODE,
@@ -577,7 +577,7 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
 {
        struct cifsFileInfo *cfile;
 
-       cifs_get_writable_path(tcon, from_name, &cfile);
+       cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
 
        return smb2_set_path_attr(xid, tcon, from_name, to_name,
                                  cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
index e47190c..c31e84e 100644 (file)
@@ -1364,6 +1364,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
 
        cfile->fid.persistent_fid = fid->persistent_fid;
        cfile->fid.volatile_fid = fid->volatile_fid;
+       cfile->fid.access = fid->access;
 #ifdef CONFIG_CIFS_DEBUG2
        cfile->fid.mid = fid->mid;
 #endif /* CIFS_DEBUG2 */
@@ -3327,7 +3328,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs
         * some servers (Windows2016) will not reflect recent writes in
         * QUERY_ALLOCATED_RANGES until SMB2_flush is called.
         */
-       wrcfile = find_writable_file(cifsi, false);
+       wrcfile = find_writable_file(cifsi, FIND_WR_ANY);
        if (wrcfile) {
                filemap_write_and_wait(inode->i_mapping);
                smb2_flush_file(xid, tcon, &wrcfile->fid);
index 1234f9c..28c0be5 100644 (file)
@@ -2771,6 +2771,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        atomic_inc(&tcon->num_remote_opens);
        oparms->fid->persistent_fid = rsp->PersistentFileId;
        oparms->fid->volatile_fid = rsp->VolatileFileId;
+       oparms->fid->access = oparms->desired_access;
 #ifdef CONFIG_CIFS_DEBUG2
        oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId);
 #endif /* CIFS_DEBUG2 */
index 65cb09f..08c9f21 100644 (file)
@@ -539,6 +539,15 @@ int fscrypt_drop_inode(struct inode *inode)
        mk = ci->ci_master_key->payload.data[0];
 
        /*
+        * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
+        * protected by the key were cleaned by sync_filesystem().  But if
+        * userspace is still using the files, inodes can be dirtied between
+        * then and now.  We mustn't lose any writes, so skip dirty inodes here.
+        */
+       if (inode->i_state & I_DIRTY_ALL)
+               return 0;
+
+       /*
         * Note: since we aren't holding ->mk_secret_sem, the result here can
         * immediately become outdated.  But there's no correctness problem with
         * unnecessarily evicting.  Nor is there a correctness problem with not
index 634b09d..db987b5 100644 (file)
@@ -1090,21 +1090,12 @@ static const struct file_operations fops_regset32 = {
  * This function creates a file in debugfs with the given name that reports
  * the names and values of a set of 32-bit registers. If the @mode variable
  * is so set it can be read from. Writing is not supported.
- *
- * This function will return a pointer to a dentry if it succeeds.  This
- * pointer must be passed to the debugfs_remove() function when the file is
- * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, ERR_PTR(-ERROR) will be
- * returned.
- *
- * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
- * be returned.
  */
-struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
-                                      struct dentry *parent,
-                                      struct debugfs_regset32 *regset)
+void debugfs_create_regset32(const char *name, umode_t mode,
+                            struct dentry *parent,
+                            struct debugfs_regset32 *regset)
 {
-       return debugfs_create_file(name, mode, parent, regset, &fops_regset32);
+       debugfs_create_file(name, mode, parent, regset, &fops_regset32);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_regset32);
 
index ff1b764..0c7c4ad 100644 (file)
@@ -2391,7 +2391,7 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct flex_groups **old_groups, **new_groups;
-       int size, i;
+       int size, i, j;
 
        if (!sbi->s_log_groups_per_flex)
                return 0;
@@ -2412,8 +2412,8 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
                                         sizeof(struct flex_groups)),
                                         GFP_KERNEL);
                if (!new_groups[i]) {
-                       for (i--; i >= sbi->s_flex_groups_allocated; i--)
-                               kvfree(new_groups[i]);
+                       for (j = sbi->s_flex_groups_allocated; j < i; j++)
+                               kvfree(new_groups[j]);
                        kvfree(new_groups);
                        ext4_msg(sb, KERN_ERR,
                                 "not enough memory for %d flex groups", size);
index 594b05a..71946da 100644 (file)
@@ -750,6 +750,13 @@ static struct inode *fat_alloc_inode(struct super_block *sb)
                return NULL;
 
        init_rwsem(&ei->truncate_lock);
+       /* Zeroing to allow iput() even if partial initialized inode. */
+       ei->mmu_private = 0;
+       ei->i_start = 0;
+       ei->i_logstart = 0;
+       ei->i_attrs = 0;
+       ei->i_pos = 0;
+
        return &ei->vfs_inode;
 }
 
@@ -1374,16 +1381,6 @@ out:
        return 0;
 }
 
-static void fat_dummy_inode_init(struct inode *inode)
-{
-       /* Initialize this dummy inode to work as no-op. */
-       MSDOS_I(inode)->mmu_private = 0;
-       MSDOS_I(inode)->i_start = 0;
-       MSDOS_I(inode)->i_logstart = 0;
-       MSDOS_I(inode)->i_attrs = 0;
-       MSDOS_I(inode)->i_pos = 0;
-}
-
 static int fat_read_root(struct inode *inode)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
@@ -1844,13 +1841,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        fat_inode = new_inode(sb);
        if (!fat_inode)
                goto out_fail;
-       fat_dummy_inode_init(fat_inode);
        sbi->fat_inode = fat_inode;
 
        fsinfo_inode = new_inode(sb);
        if (!fsinfo_inode)
                goto out_fail;
-       fat_dummy_inode_init(fsinfo_inode);
        fsinfo_inode->i_ino = MSDOS_FSINFO_INO;
        sbi->fsinfo_inode = fsinfo_inode;
        insert_inode_hash(fsinfo_inode);
index 9bc1675..2e4c0fa 100644 (file)
@@ -735,8 +735,9 @@ static void send_sigio_to_task(struct task_struct *p,
                return;
 
        switch (signum) {
-               kernel_siginfo_t si;
-               default:
+               default: {
+                       kernel_siginfo_t si;
+
                        /* Queue a rt signal with the appropriate fd as its
                           value.  We use SI_SIGIO as the source, not 
                           SI_KERNEL, since kernel signals always get 
@@ -769,6 +770,7 @@ static void send_sigio_to_task(struct task_struct *p,
                        si.si_fd    = fd;
                        if (!do_send_sig_info(signum, &si, p, type))
                                break;
+               }
                /* fall-through - fall back on the old plain SIGIO signal */
                case 0:
                        do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type);
index 2716d56..8294851 100644 (file)
@@ -1248,7 +1248,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
                if (!(file->f_mode & FMODE_OPENED))
                        return finish_no_open(file, d);
                dput(d);
-               return 0;
+               return excl && (flags & O_CREAT) ? -EEXIST : 0;
        }
 
        BUG_ON(d != NULL);
index 0a5ab1a..5cef075 100644 (file)
@@ -502,7 +502,7 @@ next:
                if (worker->mm)
                        work->flags |= IO_WQ_WORK_HAS_MM;
 
-               if (wq->get_work && !(work->flags & IO_WQ_WORK_INTERNAL)) {
+               if (wq->get_work) {
                        put_work = work;
                        wq->get_work(work);
                }
@@ -535,42 +535,23 @@ next:
        } while (1);
 }
 
-static inline void io_worker_spin_for_work(struct io_wqe *wqe)
-{
-       int i = 0;
-
-       while (++i < 1000) {
-               if (io_wqe_run_queue(wqe))
-                       break;
-               if (need_resched())
-                       break;
-               cpu_relax();
-       }
-}
-
 static int io_wqe_worker(void *data)
 {
        struct io_worker *worker = data;
        struct io_wqe *wqe = worker->wqe;
        struct io_wq *wq = wqe->wq;
-       bool did_work;
 
        io_worker_start(wqe, worker);
 
-       did_work = false;
        while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
                set_current_state(TASK_INTERRUPTIBLE);
 loop:
-               if (did_work)
-                       io_worker_spin_for_work(wqe);
                spin_lock_irq(&wqe->lock);
                if (io_wqe_run_queue(wqe)) {
                        __set_current_state(TASK_RUNNING);
                        io_worker_handle_work(worker);
-                       did_work = true;
                        goto loop;
                }
-               did_work = false;
                /* drops the lock on success, retry */
                if (__io_worker_idle(wqe, worker)) {
                        __release(&wqe->lock);
@@ -766,6 +747,17 @@ static bool io_wq_can_queue(struct io_wqe *wqe, struct io_wqe_acct *acct,
        return true;
 }
 
+static void io_run_cancel(struct io_wq_work *work)
+{
+       do {
+               struct io_wq_work *old_work = work;
+
+               work->flags |= IO_WQ_WORK_CANCEL;
+               work->func(&work);
+               work = (work == old_work) ? NULL : work;
+       } while (work);
+}
+
 static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
 {
        struct io_wqe_acct *acct = io_work_get_acct(wqe, work);
@@ -779,8 +771,7 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
         * It's close enough to not be an issue, fork() has the same delay.
         */
        if (unlikely(!io_wq_can_queue(wqe, acct, work))) {
-               work->flags |= IO_WQ_WORK_CANCEL;
-               work->func(&work);
+               io_run_cancel(work);
                return;
        }
 
@@ -919,8 +910,7 @@ static enum io_wq_cancel io_wqe_cancel_cb_work(struct io_wqe *wqe,
        spin_unlock_irqrestore(&wqe->lock, flags);
 
        if (found) {
-               work->flags |= IO_WQ_WORK_CANCEL;
-               work->func(&work);
+               io_run_cancel(work);
                return IO_WQ_CANCEL_OK;
        }
 
@@ -995,8 +985,7 @@ static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
        spin_unlock_irqrestore(&wqe->lock, flags);
 
        if (found) {
-               work->flags |= IO_WQ_WORK_CANCEL;
-               work->func(&work);
+               io_run_cancel(work);
                return IO_WQ_CANCEL_OK;
        }
 
@@ -1068,42 +1057,6 @@ enum io_wq_cancel io_wq_cancel_pid(struct io_wq *wq, pid_t pid)
        return ret;
 }
 
-struct io_wq_flush_data {
-       struct io_wq_work work;
-       struct completion done;
-};
-
-static void io_wq_flush_func(struct io_wq_work **workptr)
-{
-       struct io_wq_work *work = *workptr;
-       struct io_wq_flush_data *data;
-
-       data = container_of(work, struct io_wq_flush_data, work);
-       complete(&data->done);
-}
-
-/*
- * Doesn't wait for previously queued work to finish. When this completes,
- * it just means that previously queued work was started.
- */
-void io_wq_flush(struct io_wq *wq)
-{
-       struct io_wq_flush_data data;
-       int node;
-
-       for_each_node(node) {
-               struct io_wqe *wqe = wq->wqes[node];
-
-               if (!node_online(node))
-                       continue;
-               init_completion(&data.done);
-               INIT_IO_WORK(&data.work, io_wq_flush_func);
-               data.work.flags |= IO_WQ_WORK_INTERNAL;
-               io_wqe_enqueue(wqe, &data.work);
-               wait_for_completion(&data.done);
-       }
-}
-
 struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
 {
        int ret = -ENOMEM, node;
index ccc7d84..e5e15f2 100644 (file)
@@ -8,7 +8,6 @@ enum {
        IO_WQ_WORK_HAS_MM       = 2,
        IO_WQ_WORK_HASHED       = 4,
        IO_WQ_WORK_UNBOUND      = 32,
-       IO_WQ_WORK_INTERNAL     = 64,
        IO_WQ_WORK_CB           = 128,
        IO_WQ_WORK_NO_CANCEL    = 256,
        IO_WQ_WORK_CONCURRENT   = 512,
@@ -79,16 +78,10 @@ struct io_wq_work {
        pid_t task_pid;
 };
 
-#define INIT_IO_WORK(work, _func)                      \
-       do {                                            \
-               (work)->list.next = NULL;               \
-               (work)->func = _func;                   \
-               (work)->files = NULL;                   \
-               (work)->mm = NULL;                      \
-               (work)->creds = NULL;                   \
-               (work)->fs = NULL;                      \
-               (work)->flags = 0;                      \
-       } while (0)                                     \
+#define INIT_IO_WORK(work, _func)                              \
+       do {                                                    \
+               *(work) = (struct io_wq_work){ .func = _func }; \
+       } while (0)                                             \
 
 typedef void (get_work_fn)(struct io_wq_work *);
 typedef void (put_work_fn)(struct io_wq_work *);
@@ -106,7 +99,6 @@ void io_wq_destroy(struct io_wq *wq);
 
 void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work);
 void io_wq_enqueue_hashed(struct io_wq *wq, struct io_wq_work *work, void *val);
-void io_wq_flush(struct io_wq *wq);
 
 void io_wq_cancel_all(struct io_wq *wq);
 enum io_wq_cancel io_wq_cancel_work(struct io_wq *wq, struct io_wq_work *cwork);
index de650df..c06082b 100644 (file)
@@ -183,19 +183,15 @@ struct fixed_file_table {
        struct file             **files;
 };
 
-enum {
-       FFD_F_ATOMIC,
-};
-
 struct fixed_file_data {
        struct fixed_file_table         *table;
        struct io_ring_ctx              *ctx;
 
        struct percpu_ref               refs;
        struct llist_head               put_llist;
-       unsigned long                   state;
        struct work_struct              ref_work;
        struct completion               done;
+       struct rcu_head                 rcu;
 };
 
 struct io_ring_ctx {
@@ -1004,6 +1000,7 @@ static void io_kill_timeout(struct io_kiocb *req)
        if (ret != -1) {
                atomic_inc(&req->ctx->cq_timeouts);
                list_del_init(&req->list);
+               req->flags |= REQ_F_COMP_LOCKED;
                io_cqring_fill_event(req, 0);
                io_put_req(req);
        }
@@ -1483,10 +1480,10 @@ static void io_free_req(struct io_kiocb *req)
 __attribute__((nonnull))
 static void io_put_req_find_next(struct io_kiocb *req, struct io_kiocb **nxtptr)
 {
-       io_req_find_next(req, nxtptr);
-
-       if (refcount_dec_and_test(&req->refs))
+       if (refcount_dec_and_test(&req->refs)) {
+               io_req_find_next(req, nxtptr);
                __io_free_req(req);
+       }
 }
 
 static void io_put_req(struct io_kiocb *req)
@@ -1821,6 +1818,10 @@ static void io_iopoll_req_issued(struct io_kiocb *req)
                list_add(&req->list, &ctx->poll_list);
        else
                list_add_tail(&req->list, &ctx->poll_list);
+
+       if ((ctx->flags & IORING_SETUP_SQPOLL) &&
+           wq_has_sleeper(&ctx->sqo_wait))
+               wake_up(&ctx->sqo_wait);
 }
 
 static void io_file_put(struct io_submit_state *state)
@@ -2071,7 +2072,7 @@ static ssize_t io_import_iovec(int rw, struct io_kiocb *req,
                ssize_t ret;
                ret = import_single_range(rw, buf, sqe_len, *iovec, iter);
                *iovec = NULL;
-               return ret;
+               return ret < 0 ? ret : sqe_len;
        }
 
        if (req->io) {
@@ -3002,6 +3003,11 @@ static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
 
+#ifdef CONFIG_COMPAT
+       if (req->ctx->compat)
+               sr->msg_flags |= MSG_CMSG_COMPAT;
+#endif
+
        if (!io || req->opcode == IORING_OP_SEND)
                return 0;
        /* iovec is already imported */
@@ -3154,6 +3160,11 @@ static int io_recvmsg_prep(struct io_kiocb *req,
        sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
        sr->len = READ_ONCE(sqe->len);
 
+#ifdef CONFIG_COMPAT
+       if (req->ctx->compat)
+               sr->msg_flags |= MSG_CMSG_COMPAT;
+#endif
+
        if (!io || req->opcode == IORING_OP_RECV)
                return 0;
        /* iovec is already imported */
@@ -4705,11 +4716,21 @@ static void __io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_kiocb *linked_timeout;
        struct io_kiocb *nxt = NULL;
+       const struct cred *old_creds = NULL;
        int ret;
 
 again:
        linked_timeout = io_prep_linked_timeout(req);
 
+       if (req->work.creds && req->work.creds != current_cred()) {
+               if (old_creds)
+                       revert_creds(old_creds);
+               if (old_creds == req->work.creds)
+                       old_creds = NULL; /* restored original creds */
+               else
+                       old_creds = override_creds(req->work.creds);
+       }
+
        ret = io_issue_sqe(req, sqe, &nxt, true);
 
        /*
@@ -4735,7 +4756,7 @@ punt:
 
 err:
        /* drop submission reference */
-       io_put_req(req);
+       io_put_req_find_next(req, &nxt);
 
        if (linked_timeout) {
                if (!ret)
@@ -4759,6 +4780,8 @@ done_req:
                        goto punt;
                goto again;
        }
+       if (old_creds)
+               revert_creds(old_creds);
 }
 
 static void io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
@@ -4803,7 +4826,6 @@ static inline void io_queue_link_head(struct io_kiocb *req)
 static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                          struct io_submit_state *state, struct io_kiocb **link)
 {
-       const struct cred *old_creds = NULL;
        struct io_ring_ctx *ctx = req->ctx;
        unsigned int sqe_flags;
        int ret, id;
@@ -4818,14 +4840,12 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
        id = READ_ONCE(sqe->personality);
        if (id) {
-               const struct cred *personality_creds;
-
-               personality_creds = idr_find(&ctx->personality_idr, id);
-               if (unlikely(!personality_creds)) {
+               req->work.creds = idr_find(&ctx->personality_idr, id);
+               if (unlikely(!req->work.creds)) {
                        ret = -EINVAL;
                        goto err_req;
                }
-               old_creds = override_creds(personality_creds);
+               get_cred(req->work.creds);
        }
 
        /* same numerical values with corresponding REQ_F_*, safe to copy */
@@ -4837,8 +4857,6 @@ static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 err_req:
                io_cqring_add_event(req, ret);
                io_double_put_req(req);
-               if (old_creds)
-                       revert_creds(old_creds);
                return false;
        }
 
@@ -4899,8 +4917,6 @@ err_req:
                }
        }
 
-       if (old_creds)
-               revert_creds(old_creds);
        return true;
 }
 
@@ -5081,9 +5097,8 @@ static int io_sq_thread(void *data)
        const struct cred *old_cred;
        mm_segment_t old_fs;
        DEFINE_WAIT(wait);
-       unsigned inflight;
        unsigned long timeout;
-       int ret;
+       int ret = 0;
 
        complete(&ctx->completions[1]);
 
@@ -5091,39 +5106,19 @@ static int io_sq_thread(void *data)
        set_fs(USER_DS);
        old_cred = override_creds(ctx->creds);
 
-       ret = timeout = inflight = 0;
+       timeout = jiffies + ctx->sq_thread_idle;
        while (!kthread_should_park()) {
                unsigned int to_submit;
 
-               if (inflight) {
+               if (!list_empty(&ctx->poll_list)) {
                        unsigned nr_events = 0;
 
-                       if (ctx->flags & IORING_SETUP_IOPOLL) {
-                               /*
-                                * inflight is the count of the maximum possible
-                                * entries we submitted, but it can be smaller
-                                * if we dropped some of them. If we don't have
-                                * poll entries available, then we know that we
-                                * have nothing left to poll for. Reset the
-                                * inflight count to zero in that case.
-                                */
-                               mutex_lock(&ctx->uring_lock);
-                               if (!list_empty(&ctx->poll_list))
-                                       io_iopoll_getevents(ctx, &nr_events, 0);
-                               else
-                                       inflight = 0;
-                               mutex_unlock(&ctx->uring_lock);
-                       } else {
-                               /*
-                                * Normal IO, just pretend everything completed.
-                                * We don't have to poll completions for that.
-                                */
-                               nr_events = inflight;
-                       }
-
-                       inflight -= nr_events;
-                       if (!inflight)
+                       mutex_lock(&ctx->uring_lock);
+                       if (!list_empty(&ctx->poll_list))
+                               io_iopoll_getevents(ctx, &nr_events, 0);
+                       else
                                timeout = jiffies + ctx->sq_thread_idle;
+                       mutex_unlock(&ctx->uring_lock);
                }
 
                to_submit = io_sqring_entries(ctx);
@@ -5152,7 +5147,7 @@ static int io_sq_thread(void *data)
                         * more IO, we should wait for the application to
                         * reap events and wake us up.
                         */
-                       if (inflight ||
+                       if (!list_empty(&ctx->poll_list) ||
                            (!time_after(jiffies, timeout) && ret != -EBUSY &&
                            !percpu_ref_is_dying(&ctx->refs))) {
                                cond_resched();
@@ -5162,6 +5157,19 @@ static int io_sq_thread(void *data)
                        prepare_to_wait(&ctx->sqo_wait, &wait,
                                                TASK_INTERRUPTIBLE);
 
+                       /*
+                        * While doing polled IO, before going to sleep, we need
+                        * to check if there are new reqs added to poll_list, it
+                        * is because reqs may have been punted to io worker and
+                        * will be added to poll_list later, hence check the
+                        * poll_list again.
+                        */
+                       if ((ctx->flags & IORING_SETUP_IOPOLL) &&
+                           !list_empty_careful(&ctx->poll_list)) {
+                               finish_wait(&ctx->sqo_wait, &wait);
+                               continue;
+                       }
+
                        /* Tell userspace we may need a wakeup call */
                        ctx->rings->sq_flags |= IORING_SQ_NEED_WAKEUP;
                        /* make sure to read SQ tail after writing flags */
@@ -5189,8 +5197,7 @@ static int io_sq_thread(void *data)
                mutex_lock(&ctx->uring_lock);
                ret = io_submit_sqes(ctx, to_submit, NULL, -1, &cur_mm, true);
                mutex_unlock(&ctx->uring_lock);
-               if (ret > 0)
-                       inflight += ret;
+               timeout = jiffies + ctx->sq_thread_idle;
        }
 
        set_fs(old_fs);
@@ -5324,6 +5331,26 @@ static void io_file_ref_kill(struct percpu_ref *ref)
        complete(&data->done);
 }
 
+static void __io_file_ref_exit_and_free(struct rcu_head *rcu)
+{
+       struct fixed_file_data *data = container_of(rcu, struct fixed_file_data,
+                                                       rcu);
+       percpu_ref_exit(&data->refs);
+       kfree(data);
+}
+
+static void io_file_ref_exit_and_free(struct rcu_head *rcu)
+{
+       /*
+        * We need to order our exit+free call against the potentially
+        * existing call_rcu() for switching to atomic. One way to do that
+        * is to have this rcu callback queue the final put and free, as we
+        * could otherwise have a pre-existing atomic switch complete _after_
+        * the free callback we queued.
+        */
+       call_rcu(rcu, __io_file_ref_exit_and_free);
+}
+
 static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
 {
        struct fixed_file_data *data = ctx->file_data;
@@ -5336,14 +5363,13 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
        flush_work(&data->ref_work);
        wait_for_completion(&data->done);
        io_ring_file_ref_flush(data);
-       percpu_ref_exit(&data->refs);
 
        __io_sqe_files_unregister(ctx);
        nr_tables = DIV_ROUND_UP(ctx->nr_user_files, IORING_MAX_FILES_TABLE);
        for (i = 0; i < nr_tables; i++)
                kfree(data->table[i].files);
        kfree(data->table);
-       kfree(data);
+       call_rcu(&data->rcu, io_file_ref_exit_and_free);
        ctx->file_data = NULL;
        ctx->nr_user_files = 0;
        return 0;
@@ -5595,7 +5621,6 @@ static void io_ring_file_ref_switch(struct work_struct *work)
 
        data = container_of(work, struct fixed_file_data, ref_work);
        io_ring_file_ref_flush(data);
-       percpu_ref_get(&data->refs);
        percpu_ref_switch_to_percpu(&data->refs);
 }
 
@@ -5771,8 +5796,13 @@ static void io_atomic_switch(struct percpu_ref *ref)
 {
        struct fixed_file_data *data;
 
+       /*
+        * Juggle reference to ensure we hit zero, if needed, so we can
+        * switch back to percpu mode
+        */
        data = container_of(ref, struct fixed_file_data, refs);
-       clear_bit(FFD_F_ATOMIC, &data->state);
+       percpu_ref_put(&data->refs);
+       percpu_ref_get(&data->refs);
 }
 
 static bool io_queue_file_removal(struct fixed_file_data *data,
@@ -5795,11 +5825,7 @@ static bool io_queue_file_removal(struct fixed_file_data *data,
        llist_add(&pfile->llist, &data->put_llist);
 
        if (pfile == &pfile_stack) {
-               if (!test_and_set_bit(FFD_F_ATOMIC, &data->state)) {
-                       percpu_ref_put(&data->refs);
-                       percpu_ref_switch_to_atomic(&data->refs,
-                                                       io_atomic_switch);
-               }
+               percpu_ref_switch_to_atomic(&data->refs, io_atomic_switch);
                wait_for_completion(&done);
                flush_work(&data->ref_work);
                return false;
@@ -5873,10 +5899,8 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
                up->offset++;
        }
 
-       if (ref_switch && !test_and_set_bit(FFD_F_ATOMIC, &data->state)) {
-               percpu_ref_put(&data->refs);
+       if (ref_switch)
                percpu_ref_switch_to_atomic(&data->refs, io_atomic_switch);
-       }
 
        return done ? done : err;
 }
@@ -6334,6 +6358,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
        io_sqe_buffer_unregister(ctx);
        io_sqe_files_unregister(ctx);
        io_eventfd_unregister(ctx);
+       idr_destroy(&ctx->personality_idr);
 
 #if defined(CONFIG_UNIX)
        if (ctx->ring_sock) {
@@ -6647,6 +6672,7 @@ out_fput:
        return submitted ? submitted : ret;
 }
 
+#ifdef CONFIG_PROC_FS
 static int io_uring_show_cred(int id, void *p, void *data)
 {
        const struct cred *cred = p;
@@ -6720,6 +6746,7 @@ static void io_uring_show_fdinfo(struct seq_file *m, struct file *f)
                percpu_ref_put(&ctx->refs);
        }
 }
+#endif
 
 static const struct file_operations io_uring_fops = {
        .release        = io_uring_release,
@@ -6731,7 +6758,9 @@ static const struct file_operations io_uring_fops = {
 #endif
        .poll           = io_uring_poll,
        .fasync         = io_uring_fasync,
+#ifdef CONFIG_PROC_FS
        .show_fdinfo    = io_uring_show_fdinfo,
+#endif
 };
 
 static int io_allocate_scq_urings(struct io_ring_ctx *ctx,
index d181948..3dccc23 100644 (file)
@@ -1150,8 +1150,8 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh,
        /* For undo access buffer must have data copied */
        if (undo && !jh->b_committed_data)
                goto out;
-       if (jh->b_transaction != handle->h_transaction &&
-           jh->b_next_transaction != handle->h_transaction)
+       if (READ_ONCE(jh->b_transaction) != handle->h_transaction &&
+           READ_ONCE(jh->b_next_transaction) != handle->h_transaction)
                goto out;
        /*
         * There are two reasons for the barrier here:
@@ -2569,8 +2569,8 @@ bool __jbd2_journal_refile_buffer(struct journal_head *jh)
         * our jh reference and thus __jbd2_journal_file_buffer() must not
         * take a new one.
         */
-       jh->b_transaction = jh->b_next_transaction;
-       jh->b_next_transaction = NULL;
+       WRITE_ONCE(jh->b_transaction, jh->b_next_transaction);
+       WRITE_ONCE(jh->b_next_transaction, NULL);
        if (buffer_freed(bh))
                jlist = BJ_Forget;
        else if (jh->b_modified)
index 44b6da0..426b55d 100644 (file)
@@ -753,20 +753,6 @@ int locks_delete_block(struct file_lock *waiter)
 {
        int status = -ENOENT;
 
-       /*
-        * If fl_blocker is NULL, it won't be set again as this thread
-        * "owns" the lock and is the only one that might try to claim
-        * the lock.  So it is safe to test fl_blocker locklessly.
-        * Also if fl_blocker is NULL, this waiter is not listed on
-        * fl_blocked_requests for some lock, so no other request can
-        * be added to the list of fl_blocked_requests for this
-        * request.  So if fl_blocker is NULL, it is safe to
-        * locklessly check if fl_blocked_requests is empty.  If both
-        * of these checks succeed, there is no need to take the lock.
-        */
-       if (waiter->fl_blocker == NULL &&
-           list_empty(&waiter->fl_blocked_requests))
-               return status;
        spin_lock(&blocked_lock_lock);
        if (waiter->fl_blocker)
                status = 0;
index 0788b37..b69d6ee 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -860,9 +860,6 @@ cleanup_file:
  * the return value of d_splice_alias(), then the caller needs to perform dput()
  * on it after finish_open().
  *
- * On successful return @file is a fully instantiated open file.  After this, if
- * an error occurs in ->atomic_open(), it needs to clean up with fput().
- *
  * Returns zero on success or -errno if the open failed.
  */
 int finish_open(struct file *file, struct dentry *dentry,
index fb87ad3..ef2697b 100644 (file)
@@ -2,6 +2,7 @@ config ZONEFS_FS
        tristate "zonefs filesystem support"
        depends on BLOCK
        depends on BLK_DEV_ZONED
+       select FS_IOMAP
        help
          zonefs is a simple file system which exposes zones of a zoned block
          device (e.g. host-managed or host-aware SMR disk drives) as files.
index 8bc6ef8..69aee3d 100644 (file)
@@ -601,13 +601,13 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
        ssize_t ret;
 
        /*
-        * For async direct IOs to sequential zone files, ignore IOCB_NOWAIT
+        * For async direct IOs to sequential zone files, refuse IOCB_NOWAIT
         * as this can cause write reordering (e.g. the first aio gets EAGAIN
         * on the inode lock but the second goes through but is now unaligned).
         */
-       if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && !is_sync_kiocb(iocb)
-           && (iocb->ki_flags & IOCB_NOWAIT))
-               iocb->ki_flags &= ~IOCB_NOWAIT;
+       if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && !is_sync_kiocb(iocb) &&
+           (iocb->ki_flags & IOCB_NOWAIT))
+               return -EOPNOTSUPP;
 
        if (iocb->ki_flags & IOCB_NOWAIT) {
                if (!inode_trylock(inode))
index a2583c2..4defed5 100644 (file)
@@ -532,11 +532,12 @@ typedef u64 acpi_integer;
         strnlen (a, ACPI_NAMESEG_SIZE) == ACPI_NAMESEG_SIZE)
 
 /*
- * Algorithm to obtain access bit width.
+ * Algorithm to obtain access bit or byte width.
  * Can be used with access_width of struct acpi_generic_address and access_size of
  * struct acpi_resource_generic_register.
  */
 #define ACPI_ACCESS_BIT_WIDTH(size)     (1 << ((size) + 2))
+#define ACPI_ACCESS_BYTE_WIDTH(size)    (1 << ((size) - 1))
 
 /*******************************************************************************
  *
index 4e6dc84..9ecb3c1 100644 (file)
@@ -33,7 +33,8 @@ bool __must_check curve25519(u8 mypublic[CURVE25519_KEY_SIZE],
                             const u8 secret[CURVE25519_KEY_SIZE],
                             const u8 basepoint[CURVE25519_KEY_SIZE])
 {
-       if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519))
+       if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519) &&
+           (!IS_ENABLED(CONFIG_CRYPTO_CURVE25519_X86) || IS_ENABLED(CONFIG_AS_ADX)))
                curve25519_arch(mypublic, secret, basepoint);
        else
                curve25519_generic(mypublic, secret, basepoint);
@@ -49,7 +50,8 @@ __must_check curve25519_generate_public(u8 pub[CURVE25519_KEY_SIZE],
                                    CURVE25519_KEY_SIZE)))
                return false;
 
-       if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519))
+       if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CURVE25519) &&
+           (!IS_ENABLED(CONFIG_CRYPTO_CURVE25519_X86) || IS_ENABLED(CONFIG_AS_ADX)))
                curve25519_base_arch(pub, secret);
        else
                curve25519_generic(pub, secret, curve25519_base_point);
index bcb39da..41725d8 100644 (file)
@@ -81,7 +81,7 @@ struct drm_dp_vcpi {
  * &drm_dp_mst_topology_mgr.base.lock.
  * @num_sdp_stream_sinks: Number of stream sinks. Protected by
  * &drm_dp_mst_topology_mgr.base.lock.
- * @available_pbn: Available bandwidth for this port. Protected by
+ * @full_pbn: Max possible bandwidth for this port. Protected by
  * &drm_dp_mst_topology_mgr.base.lock.
  * @next: link to next port on this branch device
  * @aux: i2c aux transport to talk to device connected to this port, protected
@@ -126,7 +126,7 @@ struct drm_dp_mst_port {
        u8 dpcd_rev;
        u8 num_sdp_streams;
        u8 num_sdp_stream_sinks;
-       uint16_t available_pbn;
+       uint16_t full_pbn;
        struct list_head next;
        /**
         * @mstb: the branch device connected to this port, if there is one.
index e34a7b7..294b293 100644 (file)
@@ -96,6 +96,11 @@ struct drm_gem_shmem_object {
         * The address are un-mapped when the count reaches zero.
         */
        unsigned int vmap_use_count;
+
+       /**
+        * @map_cached: map object cached (instead of using writecombine).
+        */
+       bool map_cached;
 };
 
 #define to_drm_gem_shmem_obj(obj) \
index 7e18c93..d11e183 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+#define BOOTCONFIG_MAGIC       "#BOOTCONFIG\n"
+#define BOOTCONFIG_MAGIC_LEN   12
+
 /* XBC tree node */
 struct xbc_node {
        u16 next;
index d7ddebd..e75d219 100644 (file)
@@ -62,6 +62,7 @@ struct css_task_iter {
        struct list_head                *mg_tasks_head;
        struct list_head                *dying_tasks_head;
 
+       struct list_head                *cur_tasks_head;
        struct css_set                  *cur_cset;
        struct css_set                  *cur_dcset;
        struct task_struct              *cur_task;
index 3d013de..43efcc4 100644 (file)
@@ -127,9 +127,9 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode,
                                  struct dentry *parent,
                                  struct debugfs_blob_wrapper *blob);
 
-struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
-                                    struct dentry *parent,
-                                    struct debugfs_regset32 *regset);
+void debugfs_create_regset32(const char *name, umode_t mode,
+                            struct dentry *parent,
+                            struct debugfs_regset32 *regset);
 
 void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
                          int nregs, void __iomem *base, char *prefix);
@@ -304,11 +304,10 @@ static inline struct dentry *debugfs_create_blob(const char *name, umode_t mode,
        return ERR_PTR(-ENODEV);
 }
 
-static inline struct dentry *debugfs_create_regset32(const char *name,
-                                  umode_t mode, struct dentry *parent,
-                                  struct debugfs_regset32 *regset)
+static inline void debugfs_create_regset32(const char *name, umode_t mode,
+                                          struct dentry *parent,
+                                          struct debugfs_regset32 *regset)
 {
-       return ERR_PTR(-ENODEV);
 }
 
 static inline void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
index 0cd7c64..fa04dfd 100644 (file)
@@ -798,6 +798,17 @@ static inline struct device_node *dev_of_node(struct device *dev)
        return dev->of_node;
 }
 
+static inline bool dev_has_sync_state(struct device *dev)
+{
+       if (!dev)
+               return false;
+       if (dev->driver && dev->driver->sync_state)
+               return true;
+       if (dev->bus && dev->bus->sync_state)
+               return true;
+       return false;
+}
+
 /*
  * High level routines for use by the bus drivers
  */
index cd41f20..875f711 100644 (file)
@@ -492,7 +492,7 @@ struct hid_report_enum {
 };
 
 #define HID_MIN_BUFFER_SIZE    64              /* make sure there is at least a packet size of space */
-#define HID_MAX_BUFFER_SIZE    4096            /* 4kb */
+#define HID_MAX_BUFFER_SIZE    8192            /* 8kb */
 #define HID_CONTROL_FIFO_SIZE  256             /* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE   64
 
index 93338fd..33d3796 100644 (file)
@@ -22,19 +22,23 @@ extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn);
 int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
                               unsigned int data_len);
 
+#if IS_ENABLED(CONFIG_NF_NAT)
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
+#else
+#define icmpv6_ndo_send icmpv6_send
+#endif
+
 #else
 
 static inline void icmpv6_send(struct sk_buff *skb,
                               u8 type, u8 code, __u32 info)
 {
-
 }
-#endif
 
-#if IS_ENABLED(CONFIG_NF_NAT)
-void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
-#else
-#define icmpv6_ndo_send icmpv6_send
+static inline void icmpv6_ndo_send(struct sk_buff *skb,
+                                  u8 type, u8 code, __u32 info)
+{
+}
 #endif
 
 extern int                             icmpv6_init(void);
index 39faaaf..c91cf2d 100644 (file)
@@ -2,15 +2,10 @@
 #ifndef _INET_DIAG_H_
 #define _INET_DIAG_H_ 1
 
+#include <net/netlink.h>
 #include <uapi/linux/inet_diag.h>
 
-struct net;
-struct sock;
 struct inet_hashinfo;
-struct nlattr;
-struct nlmsghdr;
-struct sk_buff;
-struct netlink_callback;
 
 struct inet_diag_handler {
        void            (*dump)(struct sk_buff *skb,
@@ -62,6 +57,17 @@ int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk);
 
 void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk);
 
+static inline size_t inet_diag_msg_attrs_size(void)
+{
+       return    nla_total_size(1)  /* INET_DIAG_SHUTDOWN */
+               + nla_total_size(1)  /* INET_DIAG_TOS */
+#if IS_ENABLED(CONFIG_IPV6)
+               + nla_total_size(1)  /* INET_DIAG_TCLASS */
+               + nla_total_size(1)  /* INET_DIAG_SKV6ONLY */
+#endif
+               + nla_total_size(4)  /* INET_DIAG_MARK */
+               + nla_total_size(4); /* INET_DIAG_CLASS_ID */
+}
 int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
                             struct inet_diag_msg *r, int ext,
                             struct user_namespace *user_ns, bool net_admin);
index e89eb67..bcb9b2a 100644 (file)
@@ -889,6 +889,8 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
+int kvm_arch_post_init_vm(struct kvm *kvm);
+void kvm_arch_pre_destroy_vm(struct kvm *kvm);
 
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 /*
@@ -1342,7 +1344,7 @@ static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
 #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
 
 struct kvm_vcpu *kvm_get_running_vcpu(void);
-struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 
 #ifdef CONFIG_HAVE_KVM_IRQ_BYPASS
 bool kvm_arch_has_irq_bypass(void);
index 52269e5..c54fb96 100644 (file)
@@ -2715,6 +2715,10 @@ static inline bool debug_pagealloc_enabled_static(void)
 #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP)
 extern void __kernel_map_pages(struct page *page, int numpages, int enable);
 
+/*
+ * When called in DEBUG_PAGEALLOC context, the call should most likely be
+ * guarded by debug_pagealloc_enabled() or debug_pagealloc_enabled_static()
+ */
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
 {
index ba70338..4c5eb3a 100644 (file)
@@ -333,6 +333,7 @@ struct mmc_host {
                                 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \
                                 MMC_CAP_UHS_DDR50)
 #define MMC_CAP_SYNC_RUNTIME_PM        (1 << 21)       /* Synced runtime PM suspends. */
+#define MMC_CAP_NEED_RSP_BUSY  (1 << 22)       /* Commands with R1B can't use R1. */
 #define MMC_CAP_DRIVER_TYPE_A  (1 << 23)       /* Host supports Driver Type A */
 #define MMC_CAP_DRIVER_TYPE_C  (1 << 24)       /* Host supports Driver Type C */
 #define MMC_CAP_DRIVER_TYPE_D  (1 << 25)       /* Host supports Driver Type D */
index 908d38d..5448c8b 100644 (file)
@@ -121,6 +121,7 @@ struct ip_set_ext {
        u32 timeout;
        u8 packets_op;
        u8 bytes_op;
+       bool target;
 };
 
 struct ip_set;
@@ -187,6 +188,14 @@ struct ip_set_type_variant {
        /* Return true if "b" set is the same as "a"
         * according to the create set parameters */
        bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
+       /* Region-locking is used */
+       bool region_lock;
+};
+
+struct ip_set_region {
+       spinlock_t lock;        /* Region lock */
+       size_t ext_size;        /* Size of the dynamic extensions */
+       u32 elements;           /* Number of elements vs timeout */
 };
 
 /* The core set type structure */
@@ -501,7 +510,7 @@ ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
 }
 
 #define IP_SET_INIT_KEXT(skb, opt, set)                        \
-       { .bytes = (skb)->len, .packets = 1,            \
+       { .bytes = (skb)->len, .packets = 1, .target = true,\
          .timeout = ip_set_adt_opt_timeout(opt, set) }
 
 #define IP_SET_INIT_UEXT(set)                          \
index c570e16..452e8ba 100644 (file)
@@ -357,6 +357,7 @@ struct macsec_ops;
  * is_gigabit_capable: Set to true if PHY supports 1000Mbps
  * has_fixups: Set to true if this phy has fixups/quirks.
  * suspended: Set to true if this phy has been suspended successfully.
+ * suspended_by_mdio_bus: Set to true if this phy was suspended by MDIO bus.
  * sysfs_links: Internal boolean tracking sysfs symbolic links setup/removal.
  * loopback_enabled: Set true if this phy has been loopbacked successfully.
  * state: state of the PHY for management purposes
@@ -396,6 +397,7 @@ struct phy_device {
        unsigned is_gigabit_capable:1;
        unsigned has_fixups:1;
        unsigned suspended:1;
+       unsigned suspended_by_mdio_bus:1;
        unsigned sysfs_links:1;
        unsigned loopback_enabled:1;
 
@@ -557,6 +559,7 @@ struct phy_driver {
        /*
         * Checks if the PHY generated an interrupt.
         * For multi-PHY devices with shared PHY interrupt pin
+        * Set interrupt bits have to be cleared.
         */
        int (*did_interrupt)(struct phy_device *phydev);
 
index 0bf9fdd..3b400b1 100644 (file)
@@ -11,6 +11,7 @@ struct omap2_mcspi_platform_config {
        unsigned short  num_cs;
        unsigned int regs_offset;
        unsigned int pin_dir:1;
+       size_t max_xfer_len;
 };
 
 struct omap2_mcspi_device_config {
index 276a03c..041bfa4 100644 (file)
@@ -24,7 +24,7 @@ struct platform_device {
        int             id;
        bool            id_auto;
        struct device   dev;
-       u64             dma_mask;
+       u64             platform_dma_mask;
        u32             num_resources;
        struct resource *resource;
 
index beb9a9d..70ebef8 100644 (file)
@@ -972,9 +972,9 @@ static inline int rhashtable_lookup_insert_key(
 /**
  * rhashtable_lookup_get_insert_key - lookup and insert object into hash table
  * @ht:                hash table
+ * @key:       key
  * @obj:       pointer to hash head inside object
  * @params:    hash table parameters
- * @data:      pointer to element data already in hashes
  *
  * Just like rhashtable_lookup_insert_key(), but this function returns the
  * object if it exists, NULL if it does not and the insertion was successful,
index 4261d1c..e48554e 100644 (file)
@@ -487,6 +487,19 @@ extern void wq_worker_comm(char *buf, size_t size, struct task_struct *task);
  *
  * We queue the work to the CPU on which it was submitted, but if the CPU dies
  * it can be processed by another CPU.
+ *
+ * Memory-ordering properties:  If it returns %true, guarantees that all stores
+ * preceding the call to queue_work() in the program order will be visible from
+ * the CPU which will execute @work by the time such work executes, e.g.,
+ *
+ * { x is initially 0 }
+ *
+ *   CPU0                              CPU1
+ *
+ *   WRITE_ONCE(x, 1);                 [ @work is being executed ]
+ *   r0 = queue_work(wq, work);                  r1 = READ_ONCE(x);
+ *
+ * Forbids: r0 == true && r1 == 0
  */
 static inline bool queue_work(struct workqueue_struct *wq,
                              struct work_struct *work)
@@ -546,6 +559,9 @@ static inline bool schedule_work_on(int cpu, struct work_struct *work)
  * This puts a job in the kernel-global workqueue if it was not already
  * queued and leaves it in the same position on the kernel-global
  * workqueue otherwise.
+ *
+ * Shares the same memory-ordering properties of queue_work(), cf. the
+ * DocBook header of queue_work().
  */
 static inline bool schedule_work(struct work_struct *work)
 {
index 54e227e..a259050 100644 (file)
@@ -108,6 +108,7 @@ struct fib_rule_notifier_info {
        [FRA_OIFNAME]   = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
        [FRA_PRIORITY]  = { .type = NLA_U32 }, \
        [FRA_FWMARK]    = { .type = NLA_U32 }, \
+       [FRA_TUN_ID]    = { .type = NLA_U64 }, \
        [FRA_FWMASK]    = { .type = NLA_U32 }, \
        [FRA_TABLE]     = { .type = NLA_U32 }, \
        [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
index 0a50d53..7c08437 100644 (file)
@@ -74,7 +74,7 @@
 #define DEV_MAC_TAGS_CFG_TAG_ID_M                         GENMASK(31, 16)
 #define DEV_MAC_TAGS_CFG_TAG_ID_X(x)                      (((x) & GENMASK(31, 16)) >> 16)
 #define DEV_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA                 BIT(2)
-#define DEV_MAC_TAGS_CFG_PB_ENA                           BIT(1)
+#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA                 BIT(1)
 #define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA                     BIT(0)
 
 #define DEV_MAC_ADV_CHK_CFG                               0x2c
index f0e4f36..8a22666 100644 (file)
@@ -1157,7 +1157,7 @@ struct snd_soc_pcm_runtime {
             ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
             (i)++)
 #define for_each_rtd_codec_dai_rollback(rtd, i, dai)           \
-       for (; ((--i) >= 0) && ((dai) = rtd->codec_dais[i]);)
+       for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);)
 
 void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);
 
index 2df8cec..6622912 100644 (file)
@@ -272,9 +272,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       41
+#define DM_VERSION_MINOR       42
 #define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2019-09-16)"
+#define DM_VERSION_EXTRA       "-ioctl (2020-02-27)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
index 1521073..8533bf0 100644 (file)
@@ -74,6 +74,8 @@ enum {
 #define IPPROTO_UDPLITE                IPPROTO_UDPLITE
   IPPROTO_MPLS = 137,          /* MPLS in IP (RFC 4023)                */
 #define IPPROTO_MPLS           IPPROTO_MPLS
+  IPPROTO_ETHERNET = 143,      /* Ethernet-within-IPv6 Encapsulation   */
+#define IPPROTO_ETHERNET       IPPROTO_ETHERNET
   IPPROTO_RAW = 255,           /* Raw IP packets                       */
 #define IPPROTO_RAW            IPPROTO_RAW
   IPPROTO_MPTCP = 262,         /* Multipath TCP connection             */
index 28e7dcd..f8aa8ba 100644 (file)
@@ -46,7 +46,7 @@ struct vtpm_shared_page {
        uint8_t pad;
 
        uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
-       uint32_t extra_pages[0]; /* grant IDs; length in nr_extra_pages */
+       uint32_t extra_pages[]; /* grant IDs; length in nr_extra_pages */
 };
 
 #endif
index 89a8895..850a43b 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/completion.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/semaphore.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/grant_table.h>
 #include <xen/interface/io/xenbus.h>
@@ -76,7 +77,7 @@ struct xenbus_device {
        enum xenbus_state state;
        struct completion down;
        struct work_struct work;
-       spinlock_t reclaim_lock;
+       struct semaphore reclaim_sem;
 };
 
 static inline struct xenbus_device *to_xenbus_device(struct device *dev)
index 452bc18..20a6ac3 100644 (file)
@@ -1226,13 +1226,12 @@ endif
 
 config BOOT_CONFIG
        bool "Boot config support"
-       depends on BLK_DEV_INITRD
-       default y
+       select BLK_DEV_INITRD
        help
          Extra boot config allows system admin to pass a config file as
          complemental extension of kernel cmdline when booting.
          The boot config file must be attached at the end of initramfs
-         with checksum and size.
+         with checksum, size and magic word.
          See <file:Documentation/admin-guide/bootconfig.rst> for details.
 
          If unsure, say Y.
index f95b014..ee4947a 100644 (file)
@@ -268,7 +268,6 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
 {
        struct xbc_node *knode, *vnode;
        char *end = buf + size;
-       char c = '\"';
        const char *val;
        int ret;
 
@@ -279,25 +278,20 @@ static int __init xbc_snprint_cmdline(char *buf, size_t size,
                        return ret;
 
                vnode = xbc_node_get_child(knode);
-               ret = snprintf(buf, rest(buf, end), "%s%c", xbc_namebuf,
-                               vnode ? '=' : ' ');
-               if (ret < 0)
-                       return ret;
-               buf += ret;
-               if (!vnode)
+               if (!vnode) {
+                       ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+                       if (ret < 0)
+                               return ret;
+                       buf += ret;
                        continue;
-
-               c = '\"';
+               }
                xbc_array_for_each_value(vnode, val) {
-                       ret = snprintf(buf, rest(buf, end), "%c%s", c, val);
+                       ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ",
+                                      xbc_namebuf, val);
                        if (ret < 0)
                                return ret;
                        buf += ret;
-                       c = ',';
                }
-               if (rest(buf, end) > 2)
-                       strcpy(buf, "\" ");
-               buf += 2;
        }
 
        return buf - (end - size);
@@ -335,7 +329,7 @@ static char * __init xbc_make_cmdline(const char *key)
        return new_cmdline;
 }
 
-u32 boot_config_checksum(unsigned char *p, u32 size)
+static u32 boot_config_checksum(unsigned char *p, u32 size)
 {
        u32 ret = 0;
 
@@ -374,7 +368,11 @@ static void __init setup_boot_config(const char *cmdline)
        if (!initrd_end)
                goto not_found;
 
-       hdr = (u32 *)(initrd_end - 8);
+       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
+       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+               goto not_found;
+
+       hdr = (u32 *)(data - 8);
        size = hdr[0];
        csum = hdr[1];
 
@@ -418,6 +416,14 @@ not_found:
 }
 #else
 #define setup_boot_config(cmdline)     do { } while (0)
+
+static int __init warn_bootconfig(char *str)
+{
+       pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOTCONFIG is not set.\n");
+       return 0;
+}
+early_param("bootconfig", warn_bootconfig);
+
 #endif
 
 /* Change NUL term back to "=", to make "param" the whole string. */
index 17b0d52..9ddfe2a 100644 (file)
@@ -1101,13 +1101,11 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
        audit_log_end(ab);
 }
 
-static int audit_set_feature(struct sk_buff *skb)
+static int audit_set_feature(struct audit_features *uaf)
 {
-       struct audit_features *uaf;
        int i;
 
        BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > ARRAY_SIZE(audit_feature_names));
-       uaf = nlmsg_data(nlmsg_hdr(skb));
 
        /* if there is ever a version 2 we should handle that here */
 
@@ -1175,6 +1173,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
        u32                     seq;
        void                    *data;
+       int                     data_len;
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
@@ -1188,6 +1187,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        seq  = nlh->nlmsg_seq;
        data = nlmsg_data(nlh);
+       data_len = nlmsg_len(nlh);
 
        switch (msg_type) {
        case AUDIT_GET: {
@@ -1211,7 +1211,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct audit_status     s;
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                if (s.mask & AUDIT_STATUS_ENABLED) {
                        err = audit_set_enabled(s.enabled);
                        if (err < 0)
@@ -1315,7 +1315,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return err;
                break;
        case AUDIT_SET_FEATURE:
-               err = audit_set_feature(skb);
+               if (data_len < sizeof(struct audit_features))
+                       return -EINVAL;
+               err = audit_set_feature(data);
                if (err)
                        return err;
                break;
@@ -1327,6 +1329,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
+                       char *str = data;
+
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
                                err = tty_audit_push();
@@ -1334,26 +1338,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                        break;
                        }
                        audit_log_user_recv_msg(&ab, msg_type);
-                       if (msg_type != AUDIT_USER_TTY)
+                       if (msg_type != AUDIT_USER_TTY) {
+                               /* ensure NULL termination */
+                               str[data_len - 1] = '\0';
                                audit_log_format(ab, " msg='%.*s'",
                                                 AUDIT_MESSAGE_TEXT_MAX,
-                                                (char *)data);
-                       else {
-                               int size;
-
+                                                str);
+                       } else {
                                audit_log_format(ab, " data=");
-                               size = nlmsg_len(nlh);
-                               if (size > 0 &&
-                                   ((unsigned char *)data)[size - 1] == '\0')
-                                       size--;
-                               audit_log_n_untrustedstring(ab, data, size);
+                               if (data_len > 0 && str[data_len - 1] == '\0')
+                                       data_len--;
+                               audit_log_n_untrustedstring(ab, str, data_len);
                        }
                        audit_log_end(ab);
                }
                break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
-               if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
+               if (data_len < sizeof(struct audit_rule_data))
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
                        audit_log_common_recv_msg(audit_context(), &ab,
@@ -1365,7 +1367,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        audit_log_end(ab);
                        return -EPERM;
                }
-               err = audit_rule_change(msg_type, seq, data, nlmsg_len(nlh));
+               err = audit_rule_change(msg_type, seq, data, data_len);
                break;
        case AUDIT_LIST_RULES:
                err = audit_list_rules_send(skb, seq);
@@ -1380,7 +1382,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_MAKE_EQUIV: {
                void *bufp = data;
                u32 sizes[2];
-               size_t msglen = nlmsg_len(nlh);
+               size_t msglen = data_len;
                char *old, *new;
 
                err = -EINVAL;
@@ -1456,7 +1458,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
                /* check if new data is valid */
                if ((s.enabled != 0 && s.enabled != 1) ||
                    (s.log_passwd != 0 && s.log_passwd != 1))
index b0126e9..026e34d 100644 (file)
@@ -456,6 +456,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
        bufp = data->buf;
        for (i = 0; i < data->field_count; i++) {
                struct audit_field *f = &entry->rule.fields[i];
+               u32 f_val;
 
                err = -EINVAL;
 
@@ -464,12 +465,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        goto exit_free;
 
                f->type = data->fields[i];
-               f->val = data->values[i];
+               f_val = data->values[i];
 
                /* Support legacy tests for a valid loginuid */
-               if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
+               if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) {
                        f->type = AUDIT_LOGINUID_SET;
-                       f->val = 0;
+                       f_val = 0;
                        entry->rule.pflags |= AUDIT_LOGINUID_LEGACY;
                }
 
@@ -485,7 +486,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SUID:
                case AUDIT_FSUID:
                case AUDIT_OBJ_UID:
-                       f->uid = make_kuid(current_user_ns(), f->val);
+                       f->uid = make_kuid(current_user_ns(), f_val);
                        if (!uid_valid(f->uid))
                                goto exit_free;
                        break;
@@ -494,11 +495,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_SGID:
                case AUDIT_FSGID:
                case AUDIT_OBJ_GID:
-                       f->gid = make_kgid(current_user_ns(), f->val);
+                       f->gid = make_kgid(current_user_ns(), f_val);
                        if (!gid_valid(f->gid))
                                goto exit_free;
                        break;
                case AUDIT_ARCH:
+                       f->val = f_val;
                        entry->rule.arch_f = f;
                        break;
                case AUDIT_SUBJ_USER:
@@ -511,11 +513,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                case AUDIT_OBJ_TYPE:
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
+                       entry->rule.buflen += f_val;
+                       f->lsm_str = str;
                        err = security_audit_rule_init(f->type, f->op, str,
                                                       (void **)&f->lsm_rule);
                        /* Keep currently invalid fields around in case they
@@ -524,68 +528,71 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                pr_warn("audit rule for LSM \'%s\' is invalid\n",
                                        str);
                                err = 0;
-                       }
-                       if (err) {
-                               kfree(str);
+                       } else if (err)
                                goto exit_free;
-                       } else
-                               f->lsm_str = str;
                        break;
                case AUDIT_WATCH:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
-                       err = audit_to_watch(&entry->rule, str, f->val, f->op);
+                       }
+                       err = audit_to_watch(&entry->rule, str, f_val, f->op);
                        if (err) {
                                kfree(str);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_DIR:
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
-
+                       }
                        err = audit_make_tree(&entry->rule, str, f->op);
                        kfree(str);
                        if (err)
                                goto exit_free;
+                       entry->rule.buflen += f_val;
                        break;
                case AUDIT_INODE:
+                       f->val = f_val;
                        err = audit_to_inode(&entry->rule, f);
                        if (err)
                                goto exit_free;
                        break;
                case AUDIT_FILTERKEY:
-                       if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
+                       if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
-                       if (IS_ERR(str))
+                       str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
                                goto exit_free;
-                       entry->rule.buflen += f->val;
+                       }
+                       entry->rule.buflen += f_val;
                        entry->rule.filterkey = str;
                        break;
                case AUDIT_EXE:
-                       if (entry->rule.exe || f->val > PATH_MAX)
+                       if (entry->rule.exe || f_val > PATH_MAX)
                                goto exit_free;
-                       str = audit_unpack_string(&bufp, &remain, f->val);
+                       str = audit_unpack_string(&bufp, &remain, f_val);
                        if (IS_ERR(str)) {
                                err = PTR_ERR(str);
                                goto exit_free;
                        }
-                       entry->rule.buflen += f->val;
-
-                       audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
+                       audit_mark = audit_alloc_mark(&entry->rule, str, f_val);
                        if (IS_ERR(audit_mark)) {
                                kfree(str);
                                err = PTR_ERR(audit_mark);
                                goto exit_free;
                        }
+                       entry->rule.buflen += f_val;
                        entry->rule.exe = audit_mark;
                        break;
+               default:
+                       f->val = f_val;
+                       break;
                }
        }
 
index be1a1c8..f2d7cea 100644 (file)
@@ -471,6 +471,7 @@ static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
         */
        p++;
        if (p >= end) {
+               (*pos)++;
                return NULL;
        } else {
                *pos = *p;
@@ -782,7 +783,7 @@ void cgroup1_release_agent(struct work_struct *work)
 
        pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
        agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
-       if (!pathbuf || !agentbuf)
+       if (!pathbuf || !agentbuf || !strlen(agentbuf))
                goto out;
 
        spin_lock_irq(&css_set_lock);
index 75f6873..3dead04 100644 (file)
@@ -3542,21 +3542,21 @@ static int cpu_stat_show(struct seq_file *seq, void *v)
 static int cgroup_io_pressure_show(struct seq_file *seq, void *v)
 {
        struct cgroup *cgrp = seq_css(seq)->cgroup;
-       struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
+       struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;
 
        return psi_show(seq, psi, PSI_IO);
 }
 static int cgroup_memory_pressure_show(struct seq_file *seq, void *v)
 {
        struct cgroup *cgrp = seq_css(seq)->cgroup;
-       struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
+       struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;
 
        return psi_show(seq, psi, PSI_MEM);
 }
 static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
 {
        struct cgroup *cgrp = seq_css(seq)->cgroup;
-       struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
+       struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;
 
        return psi_show(seq, psi, PSI_CPU);
 }
@@ -4400,12 +4400,16 @@ static void css_task_iter_advance_css_set(struct css_task_iter *it)
                }
        } while (!css_set_populated(cset) && list_empty(&cset->dying_tasks));
 
-       if (!list_empty(&cset->tasks))
+       if (!list_empty(&cset->tasks)) {
                it->task_pos = cset->tasks.next;
-       else if (!list_empty(&cset->mg_tasks))
+               it->cur_tasks_head = &cset->tasks;
+       } else if (!list_empty(&cset->mg_tasks)) {
                it->task_pos = cset->mg_tasks.next;
-       else
+               it->cur_tasks_head = &cset->mg_tasks;
+       } else {
                it->task_pos = cset->dying_tasks.next;
+               it->cur_tasks_head = &cset->dying_tasks;
+       }
 
        it->tasks_head = &cset->tasks;
        it->mg_tasks_head = &cset->mg_tasks;
@@ -4463,10 +4467,14 @@ repeat:
                else
                        it->task_pos = it->task_pos->next;
 
-               if (it->task_pos == it->tasks_head)
+               if (it->task_pos == it->tasks_head) {
                        it->task_pos = it->mg_tasks_head->next;
-               if (it->task_pos == it->mg_tasks_head)
+                       it->cur_tasks_head = it->mg_tasks_head;
+               }
+               if (it->task_pos == it->mg_tasks_head) {
                        it->task_pos = it->dying_tasks_head->next;
+                       it->cur_tasks_head = it->dying_tasks_head;
+               }
                if (it->task_pos == it->dying_tasks_head)
                        css_task_iter_advance_css_set(it);
        } else {
@@ -4485,11 +4493,12 @@ repeat:
                        goto repeat;
 
                /* and dying leaders w/o live member threads */
-               if (!atomic_read(&task->signal->live))
+               if (it->cur_tasks_head == it->dying_tasks_head &&
+                   !atomic_read(&task->signal->live))
                        goto repeat;
        } else {
                /* skip all dying ones */
-               if (task->flags & PF_EXITING)
+               if (it->cur_tasks_head == it->dying_tasks_head)
                        goto repeat;
        }
 }
@@ -4595,6 +4604,9 @@ static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos)
        struct kernfs_open_file *of = s->private;
        struct css_task_iter *it = of->priv;
 
+       if (pos)
+               (*pos)++;
+
        return css_task_iter_next(it);
 }
 
@@ -4610,7 +4622,7 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
         * from position 0, so we can simply keep iterating on !0 *pos.
         */
        if (!it) {
-               if (WARN_ON_ONCE((*pos)++))
+               if (WARN_ON_ONCE((*pos)))
                        return ERR_PTR(-EINVAL);
 
                it = kzalloc(sizeof(*it), GFP_KERNEL);
@@ -4618,10 +4630,11 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
                        return ERR_PTR(-ENOMEM);
                of->priv = it;
                css_task_iter_start(&cgrp->self, iter_flags, it);
-       } else if (!(*pos)++) {
+       } else if (!(*pos)) {
                css_task_iter_end(it);
                css_task_iter_start(&cgrp->self, iter_flags, it);
-       }
+       } else
+               return it->cur_task;
 
        return cgroup_procs_next(s, NULL, NULL);
 }
@@ -6258,6 +6271,10 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd)
                return;
        }
 
+       /* Don't associate the sock with unrelated interrupted task's cgroup. */
+       if (in_interrupt())
+               return;
+
        rcu_read_lock();
 
        while (true) {
index 2833ffb..0b81b26 100644 (file)
@@ -619,8 +619,8 @@ static void forget_original_parent(struct task_struct *father,
        reaper = find_new_reaper(father, reaper);
        list_for_each_entry(p, &father->children, sibling) {
                for_each_thread(p, t) {
-                       t->real_parent = reaper;
-                       BUG_ON((!t->ptrace) != (t->parent == father));
+                       RCU_INIT_POINTER(t->real_parent, reaper);
+                       BUG_ON((!t->ptrace) != (rcu_access_pointer(t->parent) == father));
                        if (likely(!t->ptrace))
                                t->parent = t->real_parent;
                        if (t->pdeath_signal)
index 60a1295..8642530 100644 (file)
@@ -1508,7 +1508,7 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
                return 0;
        }
        sig = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
-       rcu_assign_pointer(tsk->sighand, sig);
+       RCU_INIT_POINTER(tsk->sighand, sig);
        if (!sig)
                return -ENOMEM;
 
index 0f4ecb5..647b4bb 100644 (file)
@@ -247,6 +247,16 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid,
                tmp = tmp->parent;
        }
 
+       /*
+        * ENOMEM is not the most obvious choice especially for the case
+        * where the child subreaper has already exited and the pid
+        * namespace denies the creation of any new processes. But ENOMEM
+        * is what we have exposed to userspace for a long time and it is
+        * documented behavior for pid namespaces. So we can't easily
+        * change it even if there were an error code better suited.
+        */
+       retval = -ENOMEM;
+
        if (unlikely(is_child_reaper(pid))) {
                if (pid_ns_prepare_proc(ns))
                        goto out_free;
index ddade80..d82b7b8 100644 (file)
@@ -1681,7 +1681,7 @@ static unsigned long minimum_image_size(unsigned long saveable)
  * hibernation for allocations made while saving the image and for device
  * drivers, in case they need to allocate memory from their hibernation
  * callbacks (these two numbers are given by PAGES_FOR_IO (which is a rough
- * estimate) and reserverd_size divided by PAGE_SIZE (which is tunable through
+ * estimate) and reserved_size divided by PAGE_SIZE (which is tunable through
  * /sys/power/reserved_size, respectively).  To make this happen, we compute the
  * total number of available page frames and allocate at least
  *
index 3c8a379..c1217bf 100644 (file)
@@ -8337,6 +8337,8 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd,
 
        sgs->group_capacity = group->sgc->capacity;
 
+       sgs->group_weight = group->group_weight;
+
        sgs->group_type = group_classify(sd->imbalance_pct, group, sgs);
 
        /*
index 9ad8dea..5b23963 100644 (file)
@@ -413,27 +413,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
 {
        struct sigqueue *q = NULL;
        struct user_struct *user;
+       int sigpending;
 
        /*
         * Protect access to @t credentials. This can go away when all
         * callers hold rcu read lock.
+        *
+        * NOTE! A pending signal will hold on to the user refcount,
+        * and we get/put the refcount only when the sigpending count
+        * changes from/to zero.
         */
        rcu_read_lock();
-       user = get_uid(__task_cred(t)->user);
-       atomic_inc(&user->sigpending);
+       user = __task_cred(t)->user;
+       sigpending = atomic_inc_return(&user->sigpending);
+       if (sigpending == 1)
+               get_uid(user);
        rcu_read_unlock();
 
-       if (override_rlimit ||
-           atomic_read(&user->sigpending) <=
-                       task_rlimit(t, RLIMIT_SIGPENDING)) {
+       if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) {
                q = kmem_cache_alloc(sigqueue_cachep, flags);
        } else {
                print_dropped_signal(sig);
        }
 
        if (unlikely(q == NULL)) {
-               atomic_dec(&user->sigpending);
-               free_uid(user);
+               if (atomic_dec_and_test(&user->sigpending))
+                       free_uid(user);
        } else {
                INIT_LIST_HEAD(&q->list);
                q->flags = 0;
@@ -447,8 +452,8 @@ static void __sigqueue_free(struct sigqueue *q)
 {
        if (q->flags & SIGQUEUE_PREALLOC)
                return;
-       atomic_dec(&q->user->sigpending);
-       free_uid(q->user);
+       if (atomic_dec_and_test(&q->user->sigpending))
+               free_uid(q->user);
        kmem_cache_free(sigqueue_cachep, q);
 }
 
index 91e8851..402eef8 100644 (file)
@@ -143,8 +143,8 @@ if FTRACE
 
 config BOOTTIME_TRACING
        bool "Boot-time Tracing support"
-       depends on BOOT_CONFIG && TRACING
-       default y
+       depends on TRACING
+       select BOOT_CONFIG
        help
          Enable developer to setup ftrace subsystem via supplemental
          kernel cmdline at boot time for debugging (tracing) driver
index 3f7ee10..fd81c7d 100644 (file)
@@ -1547,6 +1547,8 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
                rec = bsearch(&key, pg->records, pg->index,
                              sizeof(struct dyn_ftrace),
                              ftrace_cmp_recs);
+               if (rec)
+                       break;
        }
        return rec;
 }
index 4aefe00..7d56d62 100644 (file)
@@ -111,11 +111,11 @@ static int __init test_gen_synth_cmd(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"hula hoops";    /* next_comm_field */
+       vals[1] = (u64)(long)"hula hoops";      /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 598;                  /* my_int_field */
 
        /* Now generate a gen_synth_test event */
@@ -218,11 +218,11 @@ static int __init test_empty_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed_2.0";    /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed_2.0";      /* my_string_field */
        vals[6] = 399;                  /* my_int_field */
 
        /* Now trace an empty_synth_test event */
@@ -290,11 +290,11 @@ static int __init test_create_synth_event(void)
        /* Create some bogus values just for testing */
 
        vals[0] = 777;                  /* next_pid_field */
-       vals[1] = (u64)"tiddlywinks";   /* next_comm_field */
+       vals[1] = (u64)(long)"tiddlywinks";     /* next_comm_field */
        vals[2] = 1000000;              /* ts_ns */
        vals[3] = 1000;                 /* ts_ms */
-       vals[4] = smp_processor_id();   /* cpu */
-       vals[5] = (u64)"thneed";        /* my_string_field */
+       vals[4] = raw_smp_processor_id(); /* cpu */
+       vals[5] = (u64)(long)"thneed";  /* my_string_field */
        vals[6] = 398;                  /* my_int_field */
 
        /* Now generate a create_synth_test event */
@@ -330,7 +330,7 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* next_comm_field */
-       ret = synth_event_add_next_val((u64)"slinky", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"slinky", &trace_state);
        if (ret)
                goto out;
 
@@ -345,12 +345,12 @@ static int __init test_add_next_synth_val(void)
                goto out;
 
        /* cpu */
-       ret = synth_event_add_next_val(smp_processor_id(), &trace_state);
+       ret = synth_event_add_next_val(raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
        /* my_string_field */
-       ret = synth_event_add_next_val((u64)"thneed_2.01", &trace_state);
+       ret = synth_event_add_next_val((u64)(long)"thneed_2.01", &trace_state);
        if (ret)
                goto out;
 
@@ -388,7 +388,7 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("cpu", smp_processor_id(), &trace_state);
+       ret = synth_event_add_val("cpu", raw_smp_processor_id(), &trace_state);
        if (ret)
                goto out;
 
@@ -396,12 +396,12 @@ static int __init test_add_synth_val(void)
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("next_comm_field", (u64)"silly putty",
+       ret = synth_event_add_val("next_comm_field", (u64)(long)"silly putty",
                                  &trace_state);
        if (ret)
                goto out;
 
-       ret = synth_event_add_val("my_string_field", (u64)"thneed_9",
+       ret = synth_event_add_val("my_string_field", (u64)(long)"thneed_9",
                                  &trace_state);
        if (ret)
                goto out;
@@ -423,13 +423,13 @@ static int __init test_trace_synth_event(void)
 
        /* Trace some bogus values just for testing */
        ret = synth_event_trace(create_synth_test, 7,   /* number of values */
-                               444,                    /* next_pid_field */
-                               (u64)"clackers",        /* next_comm_field */
-                               1000000,                /* ts_ns */
-                               1000,                   /* ts_ms */
-                               smp_processor_id(),     /* cpu */
-                               (u64)"Thneed",          /* my_string_field */
-                               999);                   /* my_int_field */
+                               (u64)444,               /* next_pid_field */
+                               (u64)(long)"clackers",  /* next_comm_field */
+                               (u64)1000000,           /* ts_ns */
+                               (u64)1000,              /* ts_ms */
+                               (u64)raw_smp_processor_id(), /* cpu */
+                               (u64)(long)"Thneed",    /* my_string_field */
+                               (u64)999);              /* my_int_field */
        return ret;
 }
 
index c797a15..6b11e4e 100644 (file)
@@ -1837,6 +1837,7 @@ static __init int init_trace_selftests(void)
 
        pr_info("Running postponed tracer tests:\n");
 
+       tracing_selftest_running = true;
        list_for_each_entry_safe(p, n, &postponed_selftests, list) {
                /* This loop can take minutes when sanitizers are enabled, so
                 * lets make sure we allow RCU processing.
@@ -1859,6 +1860,7 @@ static __init int init_trace_selftests(void)
                list_del(&p->list);
                kfree(p);
        }
+       tracing_selftest_running = false;
 
  out:
        mutex_unlock(&trace_types_lock);
index 483b3fd..5f6834a 100644 (file)
@@ -821,6 +821,29 @@ static const char *synth_field_fmt(char *type)
        return fmt;
 }
 
+static void print_synth_event_num_val(struct trace_seq *s,
+                                     char *print_fmt, char *name,
+                                     int size, u64 val, char *space)
+{
+       switch (size) {
+       case 1:
+               trace_seq_printf(s, print_fmt, name, (u8)val, space);
+               break;
+
+       case 2:
+               trace_seq_printf(s, print_fmt, name, (u16)val, space);
+               break;
+
+       case 4:
+               trace_seq_printf(s, print_fmt, name, (u32)val, space);
+               break;
+
+       default:
+               trace_seq_printf(s, print_fmt, name, val, space);
+               break;
+       }
+}
+
 static enum print_line_t print_synth_event(struct trace_iterator *iter,
                                           int flags,
                                           struct trace_event *event)
@@ -859,10 +882,13 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter,
                } else {
                        struct trace_print_flags __flags[] = {
                            __def_gfpflag_names, {-1, NULL} };
+                       char *space = (i == se->n_fields - 1 ? "" : " ");
 
-                       trace_seq_printf(s, print_fmt, se->fields[i]->name,
-                                        entry->fields[n_u64],
-                                        i == se->n_fields - 1 ? "" : " ");
+                       print_synth_event_num_val(s, print_fmt,
+                                                 se->fields[i]->name,
+                                                 se->fields[i]->size,
+                                                 entry->fields[n_u64],
+                                                 space);
 
                        if (strcmp(se->fields[i]->type, "gfp_t") == 0) {
                                trace_seq_puts(s, " (");
@@ -1805,6 +1831,8 @@ __synth_event_trace_start(struct trace_event_file *file,
        int entry_size, fields_size = 0;
        int ret = 0;
 
+       memset(trace_state, '\0', sizeof(*trace_state));
+
        /*
         * Normal event tracing doesn't get called at all unless the
         * ENABLED bit is set (which attaches the probe thus allowing
@@ -1885,6 +1913,11 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        va_start(args, n_vals);
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                u64 val;
@@ -1898,12 +1931,30 @@ int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = val;
+                       struct synth_field *field = state.event->fields[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
        va_end(args);
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1942,6 +1993,11 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                return ret;
        }
 
+       if (n_vals != state.event->n_fields) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
                if (state.event->fields[i]->is_string) {
                        char *str_val = (char *)(long)vals[i];
@@ -1950,11 +2006,30 @@ int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       state.entry->fields[n_u64] = vals[i];
+                       struct synth_field *field = state.event->fields[i];
+                       u64 val = vals[i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&state.entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&state.entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&state.entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               state.entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
-
+out:
        __synth_event_trace_end(&state);
 
        return ret;
@@ -1997,8 +2072,6 @@ int synth_event_trace_start(struct trace_event_file *file,
        if (!trace_state)
                return -EINVAL;
 
-       memset(trace_state, '\0', sizeof(*trace_state));
-
        ret = __synth_event_trace_start(file, trace_state);
        if (ret == -ENOENT)
                ret = 0; /* just disabled, not really an error */
@@ -2069,8 +2142,25 @@ static int __synth_event_add_val(const char *field_name, u64 val,
 
                str_field = (char *)&entry->fields[field->offset];
                strscpy(str_field, str_val, STR_VAR_LEN_MAX);
-       } else
-               entry->fields[field->offset] = val;
+       } else {
+               switch (field->size) {
+               case 1:
+                       *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val;
+                       break;
+
+               case 2:
+                       *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val;
+                       break;
+
+               case 4:
+                       *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val;
+                       break;
+
+               default:
+                       trace_state->entry->fields[field->offset] = val;
+                       break;
+               }
+       }
  out:
        return ret;
 }
index 301db44..4e01c44 100644 (file)
@@ -1411,14 +1411,16 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
                return;
        rcu_read_lock();
 retry:
-       if (req_cpu == WORK_CPU_UNBOUND)
-               cpu = wq_select_unbound_cpu(raw_smp_processor_id());
-
        /* pwq which will be used unless @work is executing elsewhere */
-       if (!(wq->flags & WQ_UNBOUND))
-               pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
-       else
+       if (wq->flags & WQ_UNBOUND) {
+               if (req_cpu == WORK_CPU_UNBOUND)
+                       cpu = wq_select_unbound_cpu(raw_smp_processor_id());
                pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu));
+       } else {
+               if (req_cpu == WORK_CPU_UNBOUND)
+                       cpu = raw_smp_processor_id();
+               pwq = per_cpu_ptr(wq->cpu_pwqs, cpu);
+       }
 
        /*
         * If @work was previously on a different pool, it might still be
index 3ea601a..ec3ce7f 100644 (file)
@@ -533,7 +533,7 @@ struct xbc_node *find_match_node(struct xbc_node *node, char *k)
 
 static int __init __xbc_add_key(char *k)
 {
-       struct xbc_node *node;
+       struct xbc_node *node, *child;
 
        if (!xbc_valid_keyword(k))
                return xbc_parse_error("Invalid keyword", k);
@@ -543,8 +543,12 @@ static int __init __xbc_add_key(char *k)
 
        if (!last_parent)       /* the first level */
                node = find_match_node(xbc_nodes, k);
-       else
-               node = find_match_node(xbc_node_get_child(last_parent), k);
+       else {
+               child = xbc_node_get_child(last_parent);
+               if (child && xbc_node_is_value(child))
+                       return xbc_parse_error("Subkey is mixed with value", k);
+               node = find_match_node(child, k);
+       }
 
        if (node)
                last_parent = node;
@@ -574,10 +578,10 @@ static int __init __xbc_parse_keys(char *k)
        return __xbc_add_key(k);
 }
 
-static int __init xbc_parse_kv(char **k, char *v)
+static int __init xbc_parse_kv(char **k, char *v, int op)
 {
        struct xbc_node *prev_parent = last_parent;
-       struct xbc_node *node;
+       struct xbc_node *child;
        char *next;
        int c, ret;
 
@@ -585,12 +589,19 @@ static int __init xbc_parse_kv(char **k, char *v)
        if (ret)
                return ret;
 
+       child = xbc_node_get_child(last_parent);
+       if (child) {
+               if (xbc_node_is_key(child))
+                       return xbc_parse_error("Value is mixed with subkey", v);
+               else if (op == '=')
+                       return xbc_parse_error("Value is redefined", v);
+       }
+
        c = __xbc_parse_value(&v, &next);
        if (c < 0)
                return c;
 
-       node = xbc_add_sibling(v, XBC_VALUE);
-       if (!node)
+       if (!xbc_add_sibling(v, XBC_VALUE))
                return -ENOMEM;
 
        if (c == ',') { /* Array */
@@ -763,7 +774,7 @@ int __init xbc_init(char *buf)
 
        p = buf;
        do {
-               q = strpbrk(p, "{}=;\n#");
+               q = strpbrk(p, "{}=+;\n#");
                if (!q) {
                        p = skip_spaces(p);
                        if (*p != '\0')
@@ -774,8 +785,15 @@ int __init xbc_init(char *buf)
                c = *q;
                *q++ = '\0';
                switch (c) {
+               case '+':
+                       if (*q++ != '=') {
+                               ret = xbc_parse_error("Wrong '+' operator",
+                                                       q - 2);
+                               break;
+                       }
+                       /* Fall through */
                case '=':
-                       ret = xbc_parse_kv(&p, q);
+                       ret = xbc_parse_kv(&p, q, c);
                        break;
                case '{':
                        ret = xbc_open_brace(&p, q);
index 6d83caf..ad0699c 100644 (file)
@@ -235,6 +235,9 @@ bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
                __le64 lens[2];
        } b __aligned(16);
 
+       if (WARN_ON(src_len > INT_MAX))
+               return false;
+
        chacha_load_key(b.k, key);
 
        b.iv[0] = 0;
index b08b199..24ad53b 100644 (file)
@@ -3043,8 +3043,7 @@ void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
                return;
 
        flush_cache_range(vma, address, address + HPAGE_PMD_SIZE);
-       pmdval = *pvmw->pmd;
-       pmdp_invalidate(vma, address, pvmw->pmd);
+       pmdval = pmdp_invalidate(vma, address, pvmw->pmd);
        if (pmd_dirty(pmdval))
                set_page_dirty(page);
        entry = make_migration_entry(page, pmd_write(pmdval));
index d09776c..2058b8d 100644 (file)
@@ -6682,19 +6682,9 @@ void mem_cgroup_sk_alloc(struct sock *sk)
        if (!mem_cgroup_sockets_enabled)
                return;
 
-       /*
-        * Socket cloning can throw us here with sk_memcg already
-        * filled. It won't however, necessarily happen from
-        * process context. So the test for root memcg given
-        * the current task's memcg won't help us in this case.
-        *
-        * Respecting the original socket's memcg is a better
-        * decision in this case.
-        */
-       if (sk->sk_memcg) {
-               css_get(&sk->sk_memcg->css);
+       /* Do not associate the sock with unrelated interrupted task's memcg. */
+       if (in_interrupt())
                return;
-       }
 
        rcu_read_lock();
        memcg = mem_cgroup_from_task(current);
index 0bccc62..e8bfdf0 100644 (file)
@@ -2257,7 +2257,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
        bool ret;
        void *kaddr;
        void __user *uaddr;
-       bool force_mkyoung;
+       bool locked = false;
        struct vm_area_struct *vma = vmf->vma;
        struct mm_struct *mm = vma->vm_mm;
        unsigned long addr = vmf->address;
@@ -2282,11 +2282,11 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
         * On architectures with software "accessed" bits, we would
         * take a double page fault, so mark it accessed here.
         */
-       force_mkyoung = arch_faults_on_old_pte() && !pte_young(vmf->orig_pte);
-       if (force_mkyoung) {
+       if (arch_faults_on_old_pte() && !pte_young(vmf->orig_pte)) {
                pte_t entry;
 
                vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl);
+               locked = true;
                if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) {
                        /*
                         * Other thread has already handled the fault
@@ -2310,18 +2310,37 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
         * zeroes.
         */
        if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) {
+               if (locked)
+                       goto warn;
+
+               /* Re-validate under PTL if the page is still mapped */
+               vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl);
+               locked = true;
+               if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) {
+                       /* The PTE changed under us. Retry page fault. */
+                       ret = false;
+                       goto pte_unlock;
+               }
+
                /*
-                * Give a warn in case there can be some obscure
-                * use-case
+                * The same page can be mapped back since last copy attampt.
+                * Try to copy again under PTL.
                 */
-               WARN_ON_ONCE(1);
-               clear_page(kaddr);
+               if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) {
+                       /*
+                        * Give a warn in case there can be some obscure
+                        * use-case
+                        */
+warn:
+                       WARN_ON_ONCE(1);
+                       clear_page(kaddr);
+               }
        }
 
        ret = true;
 
 pte_unlock:
-       if (force_mkyoung)
+       if (locked)
                pte_unmap_unlock(vmf->pte, vmf->ptl);
        kunmap_atomic(kaddr);
        flush_dcache_page(dst);
index 0a54ffa..19389cd 100644 (file)
@@ -574,7 +574,13 @@ EXPORT_SYMBOL_GPL(restore_online_page_callback);
 
 void generic_online_page(struct page *page, unsigned int order)
 {
-       kernel_map_pages(page, 1 << order, 1);
+       /*
+        * Freeing the page with debug_pagealloc enabled will try to unmap it,
+        * so we should map it first. This is better than introducing a special
+        * case in page freeing fast path.
+        */
+       if (debug_pagealloc_enabled_static())
+               kernel_map_pages(page, 1 << order, 1);
        __free_pages_core(page, order);
        totalram_pages_add(1UL << order);
 #ifdef CONFIG_HIGHMEM
index 7a8e84f..311c0da 100644 (file)
@@ -161,6 +161,31 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
        return pages;
 }
 
+/*
+ * Used when setting automatic NUMA hinting protection where it is
+ * critical that a numa hinting PMD is not confused with a bad PMD.
+ */
+static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd)
+{
+       pmd_t pmdval = pmd_read_atomic(pmd);
+
+       /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       barrier();
+#endif
+
+       if (pmd_none(pmdval))
+               return 1;
+       if (pmd_trans_huge(pmdval))
+               return 0;
+       if (unlikely(pmd_bad(pmdval))) {
+               pmd_clear_bad(pmd);
+               return 1;
+       }
+
+       return 0;
+}
+
 static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                pud_t *pud, unsigned long addr, unsigned long end,
                pgprot_t newprot, int dirty_accountable, int prot_numa)
@@ -178,8 +203,17 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
                unsigned long this_pages;
 
                next = pmd_addr_end(addr, end);
-               if (!is_swap_pmd(*pmd) && !pmd_trans_huge(*pmd) && !pmd_devmap(*pmd)
-                               && pmd_none_or_clear_bad(pmd))
+
+               /*
+                * Automatic NUMA balancing walks the tables with mmap_sem
+                * held for read. It's possible a parallel update to occur
+                * between pmd_trans_huge() and a pmd_none_or_clear_bad()
+                * check leading to a false positive and clearing.
+                * Hence, it's necessary to atomically read the PMD value
+                * for all the checks.
+                */
+               if (!is_swap_pmd(*pmd) && !pmd_devmap(*pmd) &&
+                    pmd_none_or_clear_bad_unless_trans_huge(pmd))
                        goto next;
 
                /* invoke the mmu notifier if the pmd is populated */
index c8f7540..aad3ba7 100644 (file)
@@ -3386,8 +3386,6 @@ static const struct constant_table shmem_param_enums_huge[] = {
        {"always",      SHMEM_HUGE_ALWAYS },
        {"within_size", SHMEM_HUGE_WITHIN_SIZE },
        {"advise",      SHMEM_HUGE_ADVISE },
-       {"deny",        SHMEM_HUGE_DENY },
-       {"force",       SHMEM_HUGE_FORCE },
        {}
 };
 
index 43754d8..42f31c4 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/rwlock.h>
 #include <linux/zpool.h>
 #include <linux/magic.h>
 
index f020950..a7c8dd7 100644 (file)
@@ -789,6 +789,10 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
 
        lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
 
+       /* interface already disabled by batadv_iv_ogm_iface_disable */
+       if (!*ogm_buff)
+               return;
+
        /* the interface gets activated here to avoid race conditions between
         * the moment of activating the interface in
         * hardif_activate_interface() where the originator mac is set and
index dc3d2c1..0e3dbc5 100644 (file)
@@ -34,7 +34,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        const struct nf_br_ops *nf_ops;
        u8 state = BR_STATE_FORWARDING;
        const unsigned char *dest;
-       struct ethhdr *eth;
        u16 vid = 0;
 
        rcu_read_lock();
@@ -54,15 +53,14 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        BR_INPUT_SKB_CB(skb)->frag_max_size = 0;
 
        skb_reset_mac_header(skb);
-       eth = eth_hdr(skb);
        skb_pull(skb, ETH_HLEN);
 
        if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid, &state))
                goto out;
 
        if (IS_ENABLED(CONFIG_INET) &&
-           (eth->h_proto == htons(ETH_P_ARP) ||
-            eth->h_proto == htons(ETH_P_RARP)) &&
+           (eth_hdr(skb)->h_proto == htons(ETH_P_ARP) ||
+            eth_hdr(skb)->h_proto == htons(ETH_P_RARP)) &&
            br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
                br_do_proxy_suppress_arp(skb, br, vid, NULL);
        } else if (IS_ENABLED(CONFIG_IPV6) &&
index 03c7cdd..195d2d6 100644 (file)
@@ -112,7 +112,8 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
            caif_device_list(dev_net(dev));
        struct caif_device_entry *caifd;
 
-       list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
+       list_for_each_entry_rcu(caifd, &caifdevs->list, list,
+                               lockdep_rtnl_is_held()) {
                if (caifd->netdev == dev)
                        return caifd;
        }
index e10bd68..c6c985f 100644 (file)
@@ -3076,6 +3076,8 @@ static u16 skb_tx_hash(const struct net_device *dev,
 
        if (skb_rx_queue_recorded(skb)) {
                hash = skb_get_rx_queue(skb);
+               if (hash >= qoffset)
+                       hash -= qoffset;
                while (unlikely(hash >= qcount))
                        hash -= qcount;
                return hash + qoffset;
index 549ee56..b831c55 100644 (file)
@@ -2103,11 +2103,11 @@ err_action_values_put:
 
 static struct devlink_dpipe_table *
 devlink_dpipe_table_find(struct list_head *dpipe_tables,
-                        const char *table_name)
+                        const char *table_name, struct devlink *devlink)
 {
        struct devlink_dpipe_table *table;
-
-       list_for_each_entry_rcu(table, dpipe_tables, list) {
+       list_for_each_entry_rcu(table, dpipe_tables, list,
+                               lockdep_is_held(&devlink->lock)) {
                if (!strcmp(table->name, table_name))
                        return table;
        }
@@ -2226,7 +2226,7 @@ static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
 
        table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                return -EINVAL;
 
@@ -2382,7 +2382,7 @@ static int devlink_dpipe_table_counters_set(struct devlink *devlink,
        struct devlink_dpipe_table *table;
 
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                return -EINVAL;
 
@@ -3352,34 +3352,41 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
                                  struct genl_info *info,
                                  union devlink_param_value *value)
 {
+       struct nlattr *param_data;
        int len;
 
-       if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
-           !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
+       param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
+
+       if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
                return -EINVAL;
 
        switch (param->type) {
        case DEVLINK_PARAM_TYPE_U8:
-               value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
+               if (nla_len(param_data) != sizeof(u8))
+                       return -EINVAL;
+               value->vu8 = nla_get_u8(param_data);
                break;
        case DEVLINK_PARAM_TYPE_U16:
-               value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
+               if (nla_len(param_data) != sizeof(u16))
+                       return -EINVAL;
+               value->vu16 = nla_get_u16(param_data);
                break;
        case DEVLINK_PARAM_TYPE_U32:
-               value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
+               if (nla_len(param_data) != sizeof(u32))
+                       return -EINVAL;
+               value->vu32 = nla_get_u32(param_data);
                break;
        case DEVLINK_PARAM_TYPE_STRING:
-               len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
-                             nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
-               if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
+               len = strnlen(nla_data(param_data), nla_len(param_data));
+               if (len == nla_len(param_data) ||
                    len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
                        return -EINVAL;
-               strcpy(value->vstr,
-                      nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
+               strcpy(value->vstr, nla_data(param_data));
                break;
        case DEVLINK_PARAM_TYPE_BOOL:
-               value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
-                              true : false;
+               if (param_data && nla_len(param_data))
+                       return -EINVAL;
+               value->vbool = nla_get_flag(param_data);
                break;
        }
        return 0;
@@ -5951,6 +5958,8 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
        [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
        [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
        [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
+       [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
+       [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
        [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
        [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
        [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
@@ -6854,7 +6863,7 @@ bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
 
        rcu_read_lock();
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        enabled = false;
        if (table)
                enabled = table->counters_enabled;
@@ -6878,26 +6887,34 @@ int devlink_dpipe_table_register(struct devlink *devlink,
                                 void *priv, bool counter_control_extern)
 {
        struct devlink_dpipe_table *table;
-
-       if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
-               return -EEXIST;
+       int err = 0;
 
        if (WARN_ON(!table_ops->size_get))
                return -EINVAL;
 
+       mutex_lock(&devlink->lock);
+
+       if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
+                                    devlink)) {
+               err = -EEXIST;
+               goto unlock;
+       }
+
        table = kzalloc(sizeof(*table), GFP_KERNEL);
-       if (!table)
-               return -ENOMEM;
+       if (!table) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
        table->name = table_name;
        table->table_ops = table_ops;
        table->priv = priv;
        table->counter_control_extern = counter_control_extern;
 
-       mutex_lock(&devlink->lock);
        list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
+unlock:
        mutex_unlock(&devlink->lock);
-       return 0;
+       return err;
 }
 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
 
@@ -6914,7 +6931,7 @@ void devlink_dpipe_table_unregister(struct devlink *devlink,
 
        mutex_lock(&devlink->lock);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table)
                goto unlock;
        list_del_rcu(&table->list);
@@ -7071,7 +7088,7 @@ int devlink_dpipe_table_resource_set(struct devlink *devlink,
 
        mutex_lock(&devlink->lock);
        table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
-                                        table_name);
+                                        table_name, devlink);
        if (!table) {
                err = -EINVAL;
                goto out;
index 0642f91..b4c87fe 100644 (file)
@@ -53,30 +53,60 @@ static void cgrp_css_free(struct cgroup_subsys_state *css)
        kfree(css_cls_state(css));
 }
 
+/*
+ * To avoid freezing of sockets creation for tasks with big number of threads
+ * and opened sockets lets release file_lock every 1000 iterated descriptors.
+ * New sockets will already have been created with new classid.
+ */
+
+struct update_classid_context {
+       u32 classid;
+       unsigned int batch;
+};
+
+#define UPDATE_CLASSID_BATCH 1000
+
 static int update_classid_sock(const void *v, struct file *file, unsigned n)
 {
        int err;
+       struct update_classid_context *ctx = (void *)v;
        struct socket *sock = sock_from_file(file, &err);
 
        if (sock) {
                spin_lock(&cgroup_sk_update_lock);
-               sock_cgroup_set_classid(&sock->sk->sk_cgrp_data,
-                                       (unsigned long)v);
+               sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid);
                spin_unlock(&cgroup_sk_update_lock);
        }
+       if (--ctx->batch == 0) {
+               ctx->batch = UPDATE_CLASSID_BATCH;
+               return n + 1;
+       }
        return 0;
 }
 
+static void update_classid_task(struct task_struct *p, u32 classid)
+{
+       struct update_classid_context ctx = {
+               .classid = classid,
+               .batch = UPDATE_CLASSID_BATCH
+       };
+       unsigned int fd = 0;
+
+       do {
+               task_lock(p);
+               fd = iterate_fd(p->files, fd, update_classid_sock, &ctx);
+               task_unlock(p);
+               cond_resched();
+       } while (fd);
+}
+
 static void cgrp_attach(struct cgroup_taskset *tset)
 {
        struct cgroup_subsys_state *css;
        struct task_struct *p;
 
        cgroup_taskset_for_each(p, css, tset) {
-               task_lock(p);
-               iterate_fd(p->files, 0, update_classid_sock,
-                          (void *)(unsigned long)css_cls_state(css)->classid);
-               task_unlock(p);
+               update_classid_task(p, css_cls_state(css)->classid);
        }
 }
 
@@ -98,10 +128,7 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft,
 
        css_task_iter_start(css, 0, &it);
        while ((p = css_task_iter_next(&it))) {
-               task_lock(p);
-               iterate_fd(p->files, 0, update_classid_sock,
-                          (void *)(unsigned long)cs->classid);
-               task_unlock(p);
+               update_classid_task(p, cs->classid);
                cond_resched();
        }
        css_task_iter_end(&it);
index a4c8fac..8f71684 100644 (file)
@@ -1830,7 +1830,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                atomic_set(&newsk->sk_zckey, 0);
 
                sock_reset_flag(newsk, SOCK_DONE);
-               mem_cgroup_sk_alloc(newsk);
+
+               /* sk->sk_memcg will be populated at accept() time */
+               newsk->sk_memcg = NULL;
+
                cgroup_sk_alloc(&newsk->sk_cgrp_data);
 
                rcu_read_lock();
index a7662e7..760e6ea 100644 (file)
@@ -117,7 +117,9 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev,
 /* port.c */
 int dsa_port_set_state(struct dsa_port *dp, u8 state,
                       struct switchdev_trans *trans);
+int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy);
 int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy);
+void dsa_port_disable_rt(struct dsa_port *dp);
 void dsa_port_disable(struct dsa_port *dp);
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
index 774facb..ec13dc6 100644 (file)
@@ -63,7 +63,7 @@ static void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
                pr_err("DSA: failed to set STP state %u (%d)\n", state, err);
 }
 
-int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
+int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy)
 {
        struct dsa_switch *ds = dp->ds;
        int port = dp->index;
@@ -78,14 +78,31 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
        if (!dp->bridge_dev)
                dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
 
+       if (dp->pl)
+               phylink_start(dp->pl);
+
        return 0;
 }
 
-void dsa_port_disable(struct dsa_port *dp)
+int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
+{
+       int err;
+
+       rtnl_lock();
+       err = dsa_port_enable_rt(dp, phy);
+       rtnl_unlock();
+
+       return err;
+}
+
+void dsa_port_disable_rt(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
        int port = dp->index;
 
+       if (dp->pl)
+               phylink_stop(dp->pl);
+
        if (!dp->bridge_dev)
                dsa_port_set_state_now(dp, BR_STATE_DISABLED);
 
@@ -93,6 +110,13 @@ void dsa_port_disable(struct dsa_port *dp)
                ds->ops->port_disable(ds, port);
 }
 
+void dsa_port_disable(struct dsa_port *dp)
+{
+       rtnl_lock();
+       dsa_port_disable_rt(dp);
+       rtnl_unlock();
+}
+
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
 {
        struct dsa_notifier_bridge_info info = {
@@ -614,10 +638,6 @@ static int dsa_port_phylink_register(struct dsa_port *dp)
                goto err_phy_connect;
        }
 
-       rtnl_lock();
-       phylink_start(dp->pl);
-       rtnl_unlock();
-
        return 0;
 
 err_phy_connect:
@@ -628,9 +648,14 @@ err_phy_connect:
 int dsa_port_link_register_of(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
+       struct device_node *phy_np;
 
-       if (!ds->ops->adjust_link)
-               return dsa_port_phylink_register(dp);
+       if (!ds->ops->adjust_link) {
+               phy_np = of_parse_phandle(dp->dn, "phy-handle", 0);
+               if (of_phy_is_fixed_link(dp->dn) || phy_np)
+                       return dsa_port_phylink_register(dp);
+               return 0;
+       }
 
        dev_warn(ds->dev,
                 "Using legacy PHYLIB callbacks. Please migrate to PHYLINK!\n");
@@ -645,11 +670,12 @@ void dsa_port_link_unregister_of(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
 
-       if (!ds->ops->adjust_link) {
+       if (!ds->ops->adjust_link && dp->pl) {
                rtnl_lock();
                phylink_disconnect_phy(dp->pl);
                rtnl_unlock();
                phylink_destroy(dp->pl);
+               dp->pl = NULL;
                return;
        }
 
index 088c886..ddc0f92 100644 (file)
@@ -88,12 +88,10 @@ static int dsa_slave_open(struct net_device *dev)
                        goto clear_allmulti;
        }
 
-       err = dsa_port_enable(dp, dev->phydev);
+       err = dsa_port_enable_rt(dp, dev->phydev);
        if (err)
                goto clear_promisc;
 
-       phylink_start(dp->pl);
-
        return 0;
 
 clear_promisc:
@@ -114,9 +112,7 @@ static int dsa_slave_close(struct net_device *dev)
        struct net_device *master = dsa_slave_to_master(dev);
        struct dsa_port *dp = dsa_slave_to_port(dev);
 
-       phylink_stop(dp->pl);
-
-       dsa_port_disable(dp);
+       dsa_port_disable_rt(dp);
 
        dev_mc_unsync(master, dev);
        dev_uc_unsync(master, dev);
index 8977fe1..ef91975 100644 (file)
@@ -305,7 +305,8 @@ nla_put_failure:
 static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
        [ETHTOOL_A_BITSET_UNSPEC]       = { .type = NLA_REJECT },
        [ETHTOOL_A_BITSET_NOMASK]       = { .type = NLA_FLAG },
-       [ETHTOOL_A_BITSET_SIZE]         = { .type = NLA_U32 },
+       [ETHTOOL_A_BITSET_SIZE]         = NLA_POLICY_MAX(NLA_U32,
+                                                        ETHNL_MAX_BITSET_SIZE),
        [ETHTOOL_A_BITSET_BITS]         = { .type = NLA_NESTED },
        [ETHTOOL_A_BITSET_VALUE]        = { .type = NLA_BINARY },
        [ETHTOOL_A_BITSET_MASK]         = { .type = NLA_BINARY },
index b8247e3..b849f9d 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef _NET_ETHTOOL_BITSET_H
 #define _NET_ETHTOOL_BITSET_H
 
+#define ETHNL_MAX_BITSET_SIZE S16_MAX
+
 typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN];
 
 int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact);
index 2c7a38d..0672b2f 100644 (file)
@@ -21,7 +21,13 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
        [IEEE802154_ATTR_HW_ADDR] = { .type = NLA_HW_ADDR, },
        [IEEE802154_ATTR_PAN_ID] = { .type = NLA_U16, },
        [IEEE802154_ATTR_CHANNEL] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_BCN_ORD] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_SF_ORD] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_PAN_COORD] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_BAT_EXT] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_COORD_REALIGN] = { .type = NLA_U8, },
        [IEEE802154_ATTR_PAGE] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_DEV_TYPE] = { .type = NLA_U8, },
        [IEEE802154_ATTR_COORD_SHORT_ADDR] = { .type = NLA_U16, },
        [IEEE802154_ATTR_COORD_HW_ADDR] = { .type = NLA_HW_ADDR, },
        [IEEE802154_ATTR_COORD_PAN_ID] = { .type = NLA_U16, },
index 3768822..0bd10a1 100644 (file)
@@ -1724,6 +1724,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 {
        unsigned char optbuf[sizeof(struct ip_options) + 40];
        struct ip_options *opt = (struct ip_options *)optbuf;
+       int res;
 
        if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES)
                return;
@@ -1735,7 +1736,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
 
        memset(opt, 0, sizeof(struct ip_options));
        opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr);
-       if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL))
+       rcu_read_lock();
+       res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL);
+       rcu_read_unlock();
+
+       if (res)
                return;
 
        if (gateway)
index 5fd6e8e..66fdbfe 100644 (file)
@@ -56,7 +56,9 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version)
 }
 EXPORT_SYMBOL_GPL(gre_del_protocol);
 
-/* Fills in tpi and returns header length to be pulled. */
+/* Fills in tpi and returns header length to be pulled.
+ * Note that caller must use pskb_may_pull() before pulling GRE header.
+ */
 int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                     bool *csum_err, __be16 proto, int nhs)
 {
@@ -110,8 +112,14 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
         * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
         */
        if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) {
+               u8 _val, *val;
+
+               val = skb_header_pointer(skb, nhs + hdr_len,
+                                        sizeof(_val), &_val);
+               if (!val)
+                       return -EINVAL;
                tpi->proto = proto;
-               if ((*(u8 *)options & 0xF0) != 0x40)
+               if ((*val & 0xF0) != 0x40)
                        hdr_len += 4;
        }
        tpi->hdr_len = hdr_len;
index a4db79b..d545fb9 100644 (file)
@@ -482,8 +482,28 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
                }
                spin_unlock_bh(&queue->fastopenq.lock);
        }
+
 out:
        release_sock(sk);
+       if (newsk && mem_cgroup_sockets_enabled) {
+               int amt;
+
+               /* atomically get the memory usage, set and charge the
+                * newsk->sk_memcg.
+                */
+               lock_sock(newsk);
+
+               /* The socket has not been accepted yet, no need to look at
+                * newsk->sk_wmem_queued.
+                */
+               amt = sk_mem_pages(newsk->sk_forward_alloc +
+                                  atomic_read(&newsk->sk_rmem_alloc));
+               mem_cgroup_sk_alloc(newsk);
+               if (newsk->sk_memcg && amt)
+                       mem_cgroup_charge_skmem(newsk->sk_memcg, amt);
+
+               release_sock(newsk);
+       }
        if (req)
                reqsk_put(req);
        return newsk;
index f11e997..8c83775 100644 (file)
@@ -100,13 +100,9 @@ static size_t inet_sk_attr_size(struct sock *sk,
                aux = handler->idiag_get_aux_size(sk, net_admin);
 
        return    nla_total_size(sizeof(struct tcp_info))
-               + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
-               + nla_total_size(1) /* INET_DIAG_TOS */
-               + nla_total_size(1) /* INET_DIAG_TCLASS */
-               + nla_total_size(4) /* INET_DIAG_MARK */
-               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
-               + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(sizeof(struct inet_diag_msg))
+               + inet_diag_msg_attrs_size()
+               + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
                + nla_total_size(TCP_CA_NAME_MAX)
                + nla_total_size(sizeof(struct tcpvegas_info))
@@ -147,6 +143,24 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
        if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
                goto errout;
 
+       if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
+           ext & (1 << (INET_DIAG_TCLASS - 1))) {
+               u32 classid = 0;
+
+#ifdef CONFIG_SOCK_CGROUP_DATA
+               classid = sock_cgroup_classid(&sk->sk_cgrp_data);
+#endif
+               /* Fallback to socket priority if class id isn't set.
+                * Classful qdiscs use it as direct reference to class.
+                * For cgroup2 classid is always zero.
+                */
+               if (!classid)
+                       classid = sk->sk_priority;
+
+               if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
+                       goto errout;
+       }
+
        r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
        r->idiag_inode = sock_i_ino(sk);
 
@@ -284,24 +298,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                        goto errout;
        }
 
-       if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
-           ext & (1 << (INET_DIAG_TCLASS - 1))) {
-               u32 classid = 0;
-
-#ifdef CONFIG_SOCK_CGROUP_DATA
-               classid = sock_cgroup_classid(&sk->sk_cgrp_data);
-#endif
-               /* Fallback to socket priority if class id isn't set.
-                * Classful qdiscs use it as direct reference to class.
-                * For cgroup2 classid is always zero.
-                */
-               if (!classid)
-                       classid = sk->sk_priority;
-
-               if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
-                       goto errout;
-       }
-
 out:
        nlmsg_end(skb, nlh);
        return 0;
index e35736b..a93e7d1 100644 (file)
@@ -100,8 +100,9 @@ static int raw_diag_dump_one(struct sk_buff *in_skb,
        if (IS_ERR(sk))
                return PTR_ERR(sk);
 
-       rep = nlmsg_new(sizeof(struct inet_diag_msg) +
-                       sizeof(struct inet_diag_meminfo) + 64,
+       rep = nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg)) +
+                       inet_diag_msg_attrs_size() +
+                       nla_total_size(sizeof(struct inet_diag_meminfo)) + 64,
                        GFP_KERNEL);
        if (!rep) {
                sock_put(sk);
index 316ebdf..6b6b570 100644 (file)
@@ -6124,7 +6124,11 @@ static void tcp_rcv_synrecv_state_fastopen(struct sock *sk)
 {
        struct request_sock *req;
 
-       tcp_try_undo_loss(sk, false);
+       /* If we are still handling the SYNACK RTO, see if timestamp ECR allows
+        * undo. If peer SACKs triggered fast recovery, we can't undo here.
+        */
+       if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss)
+               tcp_try_undo_loss(sk, false);
 
        /* Reset rtx states to prevent spurious retransmits_timed_out() */
        tcp_sk(sk)->retrans_stamp = 0;
index 910555a..dccd228 100644 (file)
@@ -64,8 +64,9 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
                goto out;
 
        err = -ENOMEM;
-       rep = nlmsg_new(sizeof(struct inet_diag_msg) +
-                       sizeof(struct inet_diag_meminfo) + 64,
+       rep = nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg)) +
+                       inet_diag_msg_attrs_size() +
+                       nla_total_size(sizeof(struct inet_diag_meminfo)) + 64,
                        GFP_KERNEL);
        if (!rep)
                goto out;
index cb493e1..46d614b 100644 (file)
@@ -1226,11 +1226,13 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
 }
 
 static void
-cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt)
+cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires,
+                    bool del_rt, bool del_peer)
 {
        struct fib6_info *f6i;
 
-       f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len,
+       f6i = addrconf_get_prefix_route(del_peer ? &ifp->peer_addr : &ifp->addr,
+                                       ifp->prefix_len,
                                        ifp->idev->dev, 0, RTF_DEFAULT, true);
        if (f6i) {
                if (del_rt)
@@ -1293,7 +1295,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
        if (action != CLEANUP_PREFIX_RT_NOP) {
                cleanup_prefix_route(ifp, expires,
-                       action == CLEANUP_PREFIX_RT_DEL);
+                       action == CLEANUP_PREFIX_RT_DEL, false);
        }
 
        /* clean up prefsrc entries */
@@ -3345,6 +3347,10 @@ static void addrconf_dev_config(struct net_device *dev)
            (dev->type != ARPHRD_NONE) &&
            (dev->type != ARPHRD_RAWIP)) {
                /* Alas, we support only Ethernet autoconfiguration. */
+               idev = __in6_dev_get(dev);
+               if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP &&
+                   dev->flags & IFF_MULTICAST)
+                       ipv6_mc_up(idev);
                return;
        }
 
@@ -4586,12 +4592,14 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
 }
 
 static int modify_prefix_route(struct inet6_ifaddr *ifp,
-                              unsigned long expires, u32 flags)
+                              unsigned long expires, u32 flags,
+                              bool modify_peer)
 {
        struct fib6_info *f6i;
        u32 prio;
 
-       f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len,
+       f6i = addrconf_get_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
+                                       ifp->prefix_len,
                                        ifp->idev->dev, 0, RTF_DEFAULT, true);
        if (!f6i)
                return -ENOENT;
@@ -4602,7 +4610,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
                ip6_del_rt(dev_net(ifp->idev->dev), f6i);
 
                /* add new one */
-               addrconf_prefix_route(&ifp->addr, ifp->prefix_len,
+               addrconf_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr,
+                                     ifp->prefix_len,
                                      ifp->rt_priority, ifp->idev->dev,
                                      expires, flags, GFP_KERNEL);
        } else {
@@ -4624,6 +4633,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
        unsigned long timeout;
        bool was_managetempaddr;
        bool had_prefixroute;
+       bool new_peer = false;
 
        ASSERT_RTNL();
 
@@ -4655,6 +4665,13 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
                cfg->preferred_lft = timeout;
        }
 
+       if (cfg->peer_pfx &&
+           memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
+               if (!ipv6_addr_any(&ifp->peer_addr))
+                       cleanup_prefix_route(ifp, expires, true, true);
+               new_peer = true;
+       }
+
        spin_lock_bh(&ifp->lock);
        was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
        had_prefixroute = ifp->flags & IFA_F_PERMANENT &&
@@ -4670,6 +4687,9 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
        if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority)
                ifp->rt_priority = cfg->rt_priority;
 
+       if (new_peer)
+               ifp->peer_addr = *cfg->peer_pfx;
+
        spin_unlock_bh(&ifp->lock);
        if (!(ifp->flags&IFA_F_TENTATIVE))
                ipv6_ifa_notify(0, ifp);
@@ -4678,7 +4698,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
                int rc = -ENOENT;
 
                if (had_prefixroute)
-                       rc = modify_prefix_route(ifp, expires, flags);
+                       rc = modify_prefix_route(ifp, expires, flags, false);
 
                /* prefix route could have been deleted; if so restore it */
                if (rc == -ENOENT) {
@@ -4686,6 +4706,15 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
                                              ifp->rt_priority, ifp->idev->dev,
                                              expires, flags, GFP_KERNEL);
                }
+
+               if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
+                       rc = modify_prefix_route(ifp, expires, flags, true);
+
+               if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
+                       addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
+                                             ifp->rt_priority, ifp->idev->dev,
+                                             expires, flags, GFP_KERNEL);
+               }
        } else if (had_prefixroute) {
                enum cleanup_prefix_rt_t action;
                unsigned long rt_expires;
@@ -4696,7 +4725,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg)
 
                if (action != CLEANUP_PREFIX_RT_NOP) {
                        cleanup_prefix_route(ifp, rt_expires,
-                               action == CLEANUP_PREFIX_RT_DEL);
+                               action == CLEANUP_PREFIX_RT_DEL, false);
                }
        }
 
@@ -5983,9 +6012,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                if (ifp->idev->cnf.forwarding)
                        addrconf_join_anycast(ifp);
                if (!ipv6_addr_any(&ifp->peer_addr))
-                       addrconf_prefix_route(&ifp->peer_addr, 128, 0,
-                                             ifp->idev->dev, 0, 0,
-                                             GFP_ATOMIC);
+                       addrconf_prefix_route(&ifp->peer_addr, 128,
+                                             ifp->rt_priority, ifp->idev->dev,
+                                             0, 0, GFP_ATOMIC);
                break;
        case RTM_DELADDR:
                if (ifp->idev->cnf.forwarding)
index 79fc012..debdaeb 100644 (file)
@@ -183,9 +183,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                                        retv = -EBUSY;
                                        break;
                                }
-                       } else if (sk->sk_protocol != IPPROTO_TCP)
+                       } else if (sk->sk_protocol == IPPROTO_TCP) {
+                               if (sk->sk_prot != &tcpv6_prot) {
+                                       retv = -EBUSY;
+                                       break;
+                               }
                                break;
-
+                       } else {
+                               break;
+                       }
                        if (sk->sk_state != TCP_ESTABLISHED) {
                                retv = -ENOTCONN;
                                break;
index ab7f124..8c52efe 100644 (file)
@@ -268,7 +268,7 @@ static int seg6_do_srh(struct sk_buff *skb)
                skb_mac_header_rebuild(skb);
                skb_push(skb, skb->mac_len);
 
-               err = seg6_do_srh_encap(skb, tinfo->srh, NEXTHDR_NONE);
+               err = seg6_do_srh_encap(skb, tinfo->srh, IPPROTO_ETHERNET);
                if (err)
                        return err;
 
index 7cbc197..8165802 100644 (file)
@@ -282,7 +282,7 @@ static int input_action_end_dx2(struct sk_buff *skb,
        struct net_device *odev;
        struct ethhdr *eth;
 
-       if (!decap_and_validate(skb, NEXTHDR_NONE))
+       if (!decap_and_validate(skb, IPPROTO_ETHERNET))
                goto drop;
 
        if (!pskb_may_pull(skb, ETH_HLEN))
index d699833..38a0383 100644 (file)
@@ -1152,7 +1152,8 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       if (!(mpath->flags & MESH_PATH_RESOLVING))
+       if (!(mpath->flags & MESH_PATH_RESOLVING) &&
+           mesh_path_sel_is_hwmp(sdata))
                mesh_queue_preq(mpath, PREQ_Q_F_START);
 
        if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN)
index e041af2..88d7a69 100644 (file)
@@ -2959,7 +2959,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
            (auth_transaction == 2 &&
             ifmgd->auth_data->expected_transaction == 2)) {
                if (!ieee80211_mark_sta_auth(sdata, bssid))
-                       goto out_err;
+                       return; /* ignore frame -- wait for timeout */
        } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
                   auth_transaction == 2) {
                sdata_info(sdata, "SAE peer confirmed\n");
@@ -2967,10 +2967,6 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
        }
 
        cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
-       return;
- out_err:
-       mutex_unlock(&sdata->local->sta_mtx);
-       /* ignore frame -- wait for timeout */
 }
 
 #define case_WLAN(type) \
index 0e05ff0..0ba98ad 100644 (file)
@@ -4114,7 +4114,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
 
        lockdep_assert_held(&local->sta_mtx);
 
-       list_for_each_entry_rcu(sta, &local->sta_list, list) {
+       list_for_each_entry(sta, &local->sta_list, list) {
                if (sdata != sta->sdata &&
                    (!sta->sdata->bss || sta->sdata->bss != sdata->bss))
                        continue;
index 45acd87..fd2c315 100644 (file)
@@ -334,6 +334,8 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
        struct mptcp_sock *msk;
        unsigned int ack_size;
        bool ret = false;
+       bool can_ack;
+       u64 ack_seq;
        u8 tcp_fin;
 
        if (skb) {
@@ -360,9 +362,22 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
                ret = true;
        }
 
+       /* passive sockets msk will set the 'can_ack' after accept(), even
+        * if the first subflow may have the already the remote key handy
+        */
+       can_ack = true;
        opts->ext_copy.use_ack = 0;
        msk = mptcp_sk(subflow->conn);
-       if (!msk || !READ_ONCE(msk->can_ack)) {
+       if (likely(msk && READ_ONCE(msk->can_ack))) {
+               ack_seq = msk->ack_seq;
+       } else if (subflow->can_ack) {
+               mptcp_crypto_key_sha(subflow->remote_key, NULL, &ack_seq);
+               ack_seq++;
+       } else {
+               can_ack = false;
+       }
+
+       if (unlikely(!can_ack)) {
                *size = ALIGN(dss_size, 4);
                return ret;
        }
@@ -375,7 +390,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
 
        dss_size += ack_size;
 
-       opts->ext_copy.data_ack = msk->ack_seq;
+       opts->ext_copy.data_ack = ack_seq;
        opts->ext_copy.ack64 = 1;
        opts->ext_copy.use_ack = 1;
 
index e9aa680..3c19a8e 100644 (file)
@@ -543,6 +543,11 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
        }
 }
 
+static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu)
+{
+       return 0;
+}
+
 static int __mptcp_init_sock(struct sock *sk)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
@@ -551,6 +556,7 @@ static int __mptcp_init_sock(struct sock *sk)
        __set_bit(MPTCP_SEND_SPACE, &msk->flags);
 
        msk->first = NULL;
+       inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss;
 
        return 0;
 }
index 69c107f..8dd1758 100644 (file)
@@ -723,6 +723,20 @@ ip_set_rcu_get(struct net *net, ip_set_id_t index)
        return set;
 }
 
+static inline void
+ip_set_lock(struct ip_set *set)
+{
+       if (!set->variant->region_lock)
+               spin_lock_bh(&set->lock);
+}
+
+static inline void
+ip_set_unlock(struct ip_set *set)
+{
+       if (!set->variant->region_lock)
+               spin_unlock_bh(&set->lock);
+}
+
 int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
            const struct xt_action_param *par, struct ip_set_adt_opt *opt)
@@ -744,9 +758,9 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
        if (ret == -EAGAIN) {
                /* Type requests element to be completed */
                pr_debug("element must be completed, ADD is triggered\n");
-               spin_lock_bh(&set->lock);
+               ip_set_lock(set);
                set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-               spin_unlock_bh(&set->lock);
+               ip_set_unlock(set);
                ret = 1;
        } else {
                /* --return-nomatch: invert matched element */
@@ -775,9 +789,9 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 
        return ret;
 }
@@ -797,9 +811,9 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 
        return ret;
 }
@@ -1264,9 +1278,9 @@ ip_set_flush_set(struct ip_set *set)
 {
        pr_debug("set: %s\n",  set->name);
 
-       spin_lock_bh(&set->lock);
+       ip_set_lock(set);
        set->variant->flush(set);
-       spin_unlock_bh(&set->lock);
+       ip_set_unlock(set);
 }
 
 static int ip_set_flush(struct net *net, struct sock *ctnl, struct sk_buff *skb,
@@ -1713,9 +1727,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
        bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
 
        do {
-               spin_lock_bh(&set->lock);
+               ip_set_lock(set);
                ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
-               spin_unlock_bh(&set->lock);
+               ip_set_unlock(set);
                retried = true;
        } while (ret == -EAGAIN &&
                 set->variant->resize &&
index 7480ce5..e52d7b7 100644 (file)
@@ -7,13 +7,21 @@
 #include <linux/rcupdate.h>
 #include <linux/jhash.h>
 #include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/ipset/ip_set.h>
 
-#define __ipset_dereference_protected(p, c)    rcu_dereference_protected(p, c)
-#define ipset_dereference_protected(p, set) \
-       __ipset_dereference_protected(p, lockdep_is_held(&(set)->lock))
-
-#define rcu_dereference_bh_nfnl(p)     rcu_dereference_bh_check(p, 1)
+#define __ipset_dereference(p)         \
+       rcu_dereference_protected(p, 1)
+#define ipset_dereference_nfnl(p)      \
+       rcu_dereference_protected(p,    \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
+#define ipset_dereference_set(p, set)  \
+       rcu_dereference_protected(p,    \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
+               lockdep_is_held(&(set)->lock))
+#define ipset_dereference_bh_nfnl(p)   \
+       rcu_dereference_bh_check(p,     \
+               lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
 
 /* Hashing which uses arrays to resolve clashing. The hash table is resized
  * (doubled) when searching becomes too long.
@@ -72,11 +80,35 @@ struct hbucket {
                __aligned(__alignof__(u64));
 };
 
+/* Region size for locking == 2^HTABLE_REGION_BITS */
+#define HTABLE_REGION_BITS     10
+#define ahash_numof_locks(htable_bits)         \
+       ((htable_bits) < HTABLE_REGION_BITS ? 1 \
+               : jhash_size((htable_bits) - HTABLE_REGION_BITS))
+#define ahash_sizeof_regions(htable_bits)              \
+       (ahash_numof_locks(htable_bits) * sizeof(struct ip_set_region))
+#define ahash_region(n, htable_bits)           \
+       ((n) % ahash_numof_locks(htable_bits))
+#define ahash_bucket_start(h,  htable_bits)    \
+       ((htable_bits) < HTABLE_REGION_BITS ? 0 \
+               : (h) * jhash_size(HTABLE_REGION_BITS))
+#define ahash_bucket_end(h,  htable_bits)      \
+       ((htable_bits) < HTABLE_REGION_BITS ? jhash_size(htable_bits)   \
+               : ((h) + 1) * jhash_size(HTABLE_REGION_BITS))
+
+struct htable_gc {
+       struct delayed_work dwork;
+       struct ip_set *set;     /* Set the gc belongs to */
+       u32 region;             /* Last gc run position */
+};
+
 /* The hash table: the table size stored here in order to make resizing easy */
 struct htable {
        atomic_t ref;           /* References for resizing */
-       atomic_t uref;          /* References for dumping */
+       atomic_t uref;          /* References for dumping and gc */
        u8 htable_bits;         /* size of hash table == 2^htable_bits */
+       u32 maxelem;            /* Maxelem per region */
+       struct ip_set_region *hregion;  /* Region locks and ext sizes */
        struct hbucket __rcu *bucket[0]; /* hashtable buckets */
 };
 
@@ -162,6 +194,10 @@ htable_bits(u32 hashsize)
 #define NLEN                   0
 #endif /* IP_SET_HASH_WITH_NETS */
 
+#define SET_ELEM_EXPIRED(set, d)       \
+       (SET_WITH_TIMEOUT(set) &&       \
+        ip_set_timeout_expired(ext_timeout(d, set)))
+
 #endif /* _IP_SET_HASH_GEN_H */
 
 #ifndef MTYPE
@@ -205,10 +241,12 @@ htable_bits(u32 hashsize)
 #undef mtype_test_cidrs
 #undef mtype_test
 #undef mtype_uref
-#undef mtype_expire
 #undef mtype_resize
+#undef mtype_ext_size
+#undef mtype_resize_ad
 #undef mtype_head
 #undef mtype_list
+#undef mtype_gc_do
 #undef mtype_gc
 #undef mtype_gc_init
 #undef mtype_variant
@@ -247,10 +285,12 @@ htable_bits(u32 hashsize)
 #define mtype_test_cidrs       IPSET_TOKEN(MTYPE, _test_cidrs)
 #define mtype_test             IPSET_TOKEN(MTYPE, _test)
 #define mtype_uref             IPSET_TOKEN(MTYPE, _uref)
-#define mtype_expire           IPSET_TOKEN(MTYPE, _expire)
 #define mtype_resize           IPSET_TOKEN(MTYPE, _resize)
+#define mtype_ext_size         IPSET_TOKEN(MTYPE, _ext_size)
+#define mtype_resize_ad                IPSET_TOKEN(MTYPE, _resize_ad)
 #define mtype_head             IPSET_TOKEN(MTYPE, _head)
 #define mtype_list             IPSET_TOKEN(MTYPE, _list)
+#define mtype_gc_do            IPSET_TOKEN(MTYPE, _gc_do)
 #define mtype_gc               IPSET_TOKEN(MTYPE, _gc)
 #define mtype_gc_init          IPSET_TOKEN(MTYPE, _gc_init)
 #define mtype_variant          IPSET_TOKEN(MTYPE, _variant)
@@ -275,8 +315,7 @@ htable_bits(u32 hashsize)
 /* The generic hash structure */
 struct htype {
        struct htable __rcu *table; /* the hash table */
-       struct timer_list gc;   /* garbage collection when timeout enabled */
-       struct ip_set *set;     /* attached to this ip_set */
+       struct htable_gc gc;    /* gc workqueue */
        u32 maxelem;            /* max elements in the hash */
        u32 initval;            /* random jhash init value */
 #ifdef IP_SET_HASH_WITH_MARKMASK
@@ -288,21 +327,33 @@ struct htype {
 #ifdef IP_SET_HASH_WITH_NETMASK
        u8 netmask;             /* netmask value for subnets to store */
 #endif
+       struct list_head ad;    /* Resize add|del backlist */
        struct mtype_elem next; /* temporary storage for uadd */
 #ifdef IP_SET_HASH_WITH_NETS
        struct net_prefixes nets[NLEN]; /* book-keeping of prefixes */
 #endif
 };
 
+/* ADD|DEL entries saved during resize */
+struct mtype_resize_ad {
+       struct list_head list;
+       enum ipset_adt ad;      /* ADD|DEL element */
+       struct mtype_elem d;    /* Element value */
+       struct ip_set_ext ext;  /* Extensions for ADD */
+       struct ip_set_ext mext; /* Target extensions for ADD */
+       u32 flags;              /* Flags for ADD */
+};
+
 #ifdef IP_SET_HASH_WITH_NETS
 /* Network cidr size book keeping when the hash stores different
  * sized networks. cidr == real cidr + 1 to support /0.
  */
 static void
-mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_add_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
 {
        int i, j;
 
+       spin_lock_bh(&set->lock);
        /* Add in increasing prefix order, so larger cidr first */
        for (i = 0, j = -1; i < NLEN && h->nets[i].cidr[n]; i++) {
                if (j != -1) {
@@ -311,7 +362,7 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
                        j = i;
                } else if (h->nets[i].cidr[n] == cidr) {
                        h->nets[CIDR_POS(cidr)].nets[n]++;
-                       return;
+                       goto unlock;
                }
        }
        if (j != -1) {
@@ -320,24 +371,29 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 n)
        }
        h->nets[i].cidr[n] = cidr;
        h->nets[CIDR_POS(cidr)].nets[n] = 1;
+unlock:
+       spin_unlock_bh(&set->lock);
 }
 
 static void
-mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
+mtype_del_cidr(struct ip_set *set, struct htype *h, u8 cidr, u8 n)
 {
        u8 i, j, net_end = NLEN - 1;
 
+       spin_lock_bh(&set->lock);
        for (i = 0; i < NLEN; i++) {
                if (h->nets[i].cidr[n] != cidr)
                        continue;
                h->nets[CIDR_POS(cidr)].nets[n]--;
                if (h->nets[CIDR_POS(cidr)].nets[n] > 0)
-                       return;
+                       goto unlock;
                for (j = i; j < net_end && h->nets[j].cidr[n]; j++)
                        h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
                h->nets[j].cidr[n] = 0;
-               return;
+               goto unlock;
        }
+unlock:
+       spin_unlock_bh(&set->lock);
 }
 #endif
 
@@ -345,7 +401,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 n)
 static size_t
 mtype_ahash_memsize(const struct htype *h, const struct htable *t)
 {
-       return sizeof(*h) + sizeof(*t);
+       return sizeof(*h) + sizeof(*t) + ahash_sizeof_regions(t->htable_bits);
 }
 
 /* Get the ith element from the array block n */
@@ -369,24 +425,29 @@ mtype_flush(struct ip_set *set)
        struct htype *h = set->data;
        struct htable *t;
        struct hbucket *n;
-       u32 i;
-
-       t = ipset_dereference_protected(h->table, set);
-       for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
-               if (!n)
-                       continue;
-               if (set->extensions & IPSET_EXT_DESTROY)
-                       mtype_ext_cleanup(set, n);
-               /* FIXME: use slab cache */
-               rcu_assign_pointer(hbucket(t, i), NULL);
-               kfree_rcu(n, rcu);
+       u32 r, i;
+
+       t = ipset_dereference_nfnl(h->table);
+       for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+               spin_lock_bh(&t->hregion[r].lock);
+               for (i = ahash_bucket_start(r, t->htable_bits);
+                    i < ahash_bucket_end(r, t->htable_bits); i++) {
+                       n = __ipset_dereference(hbucket(t, i));
+                       if (!n)
+                               continue;
+                       if (set->extensions & IPSET_EXT_DESTROY)
+                               mtype_ext_cleanup(set, n);
+                       /* FIXME: use slab cache */
+                       rcu_assign_pointer(hbucket(t, i), NULL);
+                       kfree_rcu(n, rcu);
+               }
+               t->hregion[r].ext_size = 0;
+               t->hregion[r].elements = 0;
+               spin_unlock_bh(&t->hregion[r].lock);
        }
 #ifdef IP_SET_HASH_WITH_NETS
        memset(h->nets, 0, sizeof(h->nets));
 #endif
-       set->elements = 0;
-       set->ext_size = 0;
 }
 
 /* Destroy the hashtable part of the set */
@@ -397,7 +458,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
        u32 i;
 
        for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
+               n = __ipset_dereference(hbucket(t, i));
                if (!n)
                        continue;
                if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -406,6 +467,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
                kfree(n);
        }
 
+       ip_set_free(t->hregion);
        ip_set_free(t);
 }
 
@@ -414,28 +476,21 @@ static void
 mtype_destroy(struct ip_set *set)
 {
        struct htype *h = set->data;
+       struct list_head *l, *lt;
 
        if (SET_WITH_TIMEOUT(set))
-               del_timer_sync(&h->gc);
+               cancel_delayed_work_sync(&h->gc.dwork);
 
-       mtype_ahash_destroy(set,
-                           __ipset_dereference_protected(h->table, 1), true);
+       mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
+       list_for_each_safe(l, lt, &h->ad) {
+               list_del(l);
+               kfree(l);
+       }
        kfree(h);
 
        set->data = NULL;
 }
 
-static void
-mtype_gc_init(struct ip_set *set, void (*gc)(struct timer_list *t))
-{
-       struct htype *h = set->data;
-
-       timer_setup(&h->gc, gc, 0);
-       mod_timer(&h->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ);
-       pr_debug("gc initialized, run in every %u\n",
-                IPSET_GC_PERIOD(set->timeout));
-}
-
 static bool
 mtype_same_set(const struct ip_set *a, const struct ip_set *b)
 {
@@ -454,11 +509,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
               a->extensions == b->extensions;
 }
 
-/* Delete expired elements from the hashtable */
 static void
-mtype_expire(struct ip_set *set, struct htype *h)
+mtype_gc_do(struct ip_set *set, struct htype *h, struct htable *t, u32 r)
 {
-       struct htable *t;
        struct hbucket *n, *tmp;
        struct mtype_elem *data;
        u32 i, j, d;
@@ -466,10 +519,12 @@ mtype_expire(struct ip_set *set, struct htype *h)
 #ifdef IP_SET_HASH_WITH_NETS
        u8 k;
 #endif
+       u8 htable_bits = t->htable_bits;
 
-       t = ipset_dereference_protected(h->table, set);
-       for (i = 0; i < jhash_size(t->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(t, i), 1);
+       spin_lock_bh(&t->hregion[r].lock);
+       for (i = ahash_bucket_start(r, htable_bits);
+            i < ahash_bucket_end(r, htable_bits); i++) {
+               n = __ipset_dereference(hbucket(t, i));
                if (!n)
                        continue;
                for (j = 0, d = 0; j < n->pos; j++) {
@@ -485,58 +540,100 @@ mtype_expire(struct ip_set *set, struct htype *h)
                        smp_mb__after_atomic();
 #ifdef IP_SET_HASH_WITH_NETS
                        for (k = 0; k < IPSET_NET_COUNT; k++)
-                               mtype_del_cidr(h,
+                               mtype_del_cidr(set, h,
                                        NCIDR_PUT(DCIDR_GET(data->cidr, k)),
                                        k);
 #endif
+                       t->hregion[r].elements--;
                        ip_set_ext_destroy(set, data);
-                       set->elements--;
                        d++;
                }
                if (d >= AHASH_INIT_SIZE) {
                        if (d >= n->size) {
+                               t->hregion[r].ext_size -=
+                                       ext_size(n->size, dsize);
                                rcu_assign_pointer(hbucket(t, i), NULL);
                                kfree_rcu(n, rcu);
                                continue;
                        }
                        tmp = kzalloc(sizeof(*tmp) +
-                                     (n->size - AHASH_INIT_SIZE) * dsize,
-                                     GFP_ATOMIC);
+                               (n->size - AHASH_INIT_SIZE) * dsize,
+                               GFP_ATOMIC);
                        if (!tmp)
-                               /* Still try to delete expired elements */
+                               /* Still try to delete expired elements. */
                                continue;
                        tmp->size = n->size - AHASH_INIT_SIZE;
                        for (j = 0, d = 0; j < n->pos; j++) {
                                if (!test_bit(j, n->used))
                                        continue;
                                data = ahash_data(n, j, dsize);
-                               memcpy(tmp->value + d * dsize, data, dsize);
+                               memcpy(tmp->value + d * dsize,
+                                      data, dsize);
                                set_bit(d, tmp->used);
                                d++;
                        }
                        tmp->pos = d;
-                       set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+                       t->hregion[r].ext_size -=
+                               ext_size(AHASH_INIT_SIZE, dsize);
                        rcu_assign_pointer(hbucket(t, i), tmp);
                        kfree_rcu(n, rcu);
                }
        }
+       spin_unlock_bh(&t->hregion[r].lock);
 }
 
 static void
-mtype_gc(struct timer_list *t)
+mtype_gc(struct work_struct *work)
 {
-       struct htype *h = from_timer(h, t, gc);
-       struct ip_set *set = h->set;
+       struct htable_gc *gc;
+       struct ip_set *set;
+       struct htype *h;
+       struct htable *t;
+       u32 r, numof_locks;
+       unsigned int next_run;
+
+       gc = container_of(work, struct htable_gc, dwork.work);
+       set = gc->set;
+       h = set->data;
 
-       pr_debug("called\n");
        spin_lock_bh(&set->lock);
-       mtype_expire(set, h);
+       t = ipset_dereference_set(h->table, set);
+       atomic_inc(&t->uref);
+       numof_locks = ahash_numof_locks(t->htable_bits);
+       r = gc->region++;
+       if (r >= numof_locks) {
+               r = gc->region = 0;
+       }
+       next_run = (IPSET_GC_PERIOD(set->timeout) * HZ) / numof_locks;
+       if (next_run < HZ/10)
+               next_run = HZ/10;
        spin_unlock_bh(&set->lock);
 
-       h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
-       add_timer(&h->gc);
+       mtype_gc_do(set, h, t, r);
+
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by expire: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
+
+       queue_delayed_work(system_power_efficient_wq, &gc->dwork, next_run);
+
+}
+
+static void
+mtype_gc_init(struct htable_gc *gc)
+{
+       INIT_DEFERRABLE_WORK(&gc->dwork, mtype_gc);
+       queue_delayed_work(system_power_efficient_wq, &gc->dwork, HZ);
 }
 
+static int
+mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+         struct ip_set_ext *mext, u32 flags);
+static int
+mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+         struct ip_set_ext *mext, u32 flags);
+
 /* Resize a hash: create a new hash table with doubling the hashsize
  * and inserting the elements to it. Repeat until we succeed or
  * fail due to memory pressures.
@@ -547,7 +644,7 @@ mtype_resize(struct ip_set *set, bool retried)
        struct htype *h = set->data;
        struct htable *t, *orig;
        u8 htable_bits;
-       size_t extsize, dsize = set->dsize;
+       size_t dsize = set->dsize;
 #ifdef IP_SET_HASH_WITH_NETS
        u8 flags;
        struct mtype_elem *tmp;
@@ -555,7 +652,9 @@ mtype_resize(struct ip_set *set, bool retried)
        struct mtype_elem *data;
        struct mtype_elem *d;
        struct hbucket *n, *m;
-       u32 i, j, key;
+       struct list_head *l, *lt;
+       struct mtype_resize_ad *x;
+       u32 i, j, r, nr, key;
        int ret;
 
 #ifdef IP_SET_HASH_WITH_NETS
@@ -563,10 +662,8 @@ mtype_resize(struct ip_set *set, bool retried)
        if (!tmp)
                return -ENOMEM;
 #endif
-       rcu_read_lock_bh();
-       orig = rcu_dereference_bh_nfnl(h->table);
+       orig = ipset_dereference_bh_nfnl(h->table);
        htable_bits = orig->htable_bits;
-       rcu_read_unlock_bh();
 
 retry:
        ret = 0;
@@ -583,88 +680,124 @@ retry:
                ret = -ENOMEM;
                goto out;
        }
+       t->hregion = ip_set_alloc(ahash_sizeof_regions(htable_bits));
+       if (!t->hregion) {
+               kfree(t);
+               ret = -ENOMEM;
+               goto out;
+       }
        t->htable_bits = htable_bits;
+       t->maxelem = h->maxelem / ahash_numof_locks(htable_bits);
+       for (i = 0; i < ahash_numof_locks(htable_bits); i++)
+               spin_lock_init(&t->hregion[i].lock);
 
-       spin_lock_bh(&set->lock);
-       orig = __ipset_dereference_protected(h->table, 1);
-       /* There can't be another parallel resizing, but dumping is possible */
+       /* There can't be another parallel resizing,
+        * but dumping, gc, kernel side add/del are possible
+        */
+       orig = ipset_dereference_bh_nfnl(h->table);
        atomic_set(&orig->ref, 1);
        atomic_inc(&orig->uref);
-       extsize = 0;
        pr_debug("attempt to resize set %s from %u to %u, t %p\n",
                 set->name, orig->htable_bits, htable_bits, orig);
-       for (i = 0; i < jhash_size(orig->htable_bits); i++) {
-               n = __ipset_dereference_protected(hbucket(orig, i), 1);
-               if (!n)
-                       continue;
-               for (j = 0; j < n->pos; j++) {
-                       if (!test_bit(j, n->used))
+       for (r = 0; r < ahash_numof_locks(orig->htable_bits); r++) {
+               /* Expire may replace a hbucket with another one */
+               rcu_read_lock_bh();
+               for (i = ahash_bucket_start(r, orig->htable_bits);
+                    i < ahash_bucket_end(r, orig->htable_bits); i++) {
+                       n = __ipset_dereference(hbucket(orig, i));
+                       if (!n)
                                continue;
-                       data = ahash_data(n, j, dsize);
+                       for (j = 0; j < n->pos; j++) {
+                               if (!test_bit(j, n->used))
+                                       continue;
+                               data = ahash_data(n, j, dsize);
+                               if (SET_ELEM_EXPIRED(set, data))
+                                       continue;
 #ifdef IP_SET_HASH_WITH_NETS
-                       /* We have readers running parallel with us,
-                        * so the live data cannot be modified.
-                        */
-                       flags = 0;
-                       memcpy(tmp, data, dsize);
-                       data = tmp;
-                       mtype_data_reset_flags(data, &flags);
+                               /* We have readers running parallel with us,
+                                * so the live data cannot be modified.
+                                */
+                               flags = 0;
+                               memcpy(tmp, data, dsize);
+                               data = tmp;
+                               mtype_data_reset_flags(data, &flags);
 #endif
-                       key = HKEY(data, h->initval, htable_bits);
-                       m = __ipset_dereference_protected(hbucket(t, key), 1);
-                       if (!m) {
-                               m = kzalloc(sizeof(*m) +
+                               key = HKEY(data, h->initval, htable_bits);
+                               m = __ipset_dereference(hbucket(t, key));
+                               nr = ahash_region(key, htable_bits);
+                               if (!m) {
+                                       m = kzalloc(sizeof(*m) +
                                            AHASH_INIT_SIZE * dsize,
                                            GFP_ATOMIC);
-                               if (!m) {
-                                       ret = -ENOMEM;
-                                       goto cleanup;
-                               }
-                               m->size = AHASH_INIT_SIZE;
-                               extsize += ext_size(AHASH_INIT_SIZE, dsize);
-                               RCU_INIT_POINTER(hbucket(t, key), m);
-                       } else if (m->pos >= m->size) {
-                               struct hbucket *ht;
-
-                               if (m->size >= AHASH_MAX(h)) {
-                                       ret = -EAGAIN;
-                               } else {
-                                       ht = kzalloc(sizeof(*ht) +
+                                       if (!m) {
+                                               ret = -ENOMEM;
+                                               goto cleanup;
+                                       }
+                                       m->size = AHASH_INIT_SIZE;
+                                       t->hregion[nr].ext_size +=
+                                               ext_size(AHASH_INIT_SIZE,
+                                                        dsize);
+                                       RCU_INIT_POINTER(hbucket(t, key), m);
+                               } else if (m->pos >= m->size) {
+                                       struct hbucket *ht;
+
+                                       if (m->size >= AHASH_MAX(h)) {
+                                               ret = -EAGAIN;
+                                       } else {
+                                               ht = kzalloc(sizeof(*ht) +
                                                (m->size + AHASH_INIT_SIZE)
                                                * dsize,
                                                GFP_ATOMIC);
-                                       if (!ht)
-                                               ret = -ENOMEM;
+                                               if (!ht)
+                                                       ret = -ENOMEM;
+                                       }
+                                       if (ret < 0)
+                                               goto cleanup;
+                                       memcpy(ht, m, sizeof(struct hbucket) +
+                                              m->size * dsize);
+                                       ht->size = m->size + AHASH_INIT_SIZE;
+                                       t->hregion[nr].ext_size +=
+                                               ext_size(AHASH_INIT_SIZE,
+                                                        dsize);
+                                       kfree(m);
+                                       m = ht;
+                                       RCU_INIT_POINTER(hbucket(t, key), ht);
                                }
-                               if (ret < 0)
-                                       goto cleanup;
-                               memcpy(ht, m, sizeof(struct hbucket) +
-                                             m->size * dsize);
-                               ht->size = m->size + AHASH_INIT_SIZE;
-                               extsize += ext_size(AHASH_INIT_SIZE, dsize);
-                               kfree(m);
-                               m = ht;
-                               RCU_INIT_POINTER(hbucket(t, key), ht);
-                       }
-                       d = ahash_data(m, m->pos, dsize);
-                       memcpy(d, data, dsize);
-                       set_bit(m->pos++, m->used);
+                               d = ahash_data(m, m->pos, dsize);
+                               memcpy(d, data, dsize);
+                               set_bit(m->pos++, m->used);
+                               t->hregion[nr].elements++;
 #ifdef IP_SET_HASH_WITH_NETS
-                       mtype_data_reset_flags(d, &flags);
+                               mtype_data_reset_flags(d, &flags);
 #endif
+                       }
                }
+               rcu_read_unlock_bh();
        }
-       rcu_assign_pointer(h->table, t);
-       set->ext_size = extsize;
 
-       spin_unlock_bh(&set->lock);
+       /* There can't be any other writer. */
+       rcu_assign_pointer(h->table, t);
 
        /* Give time to other readers of the set */
        synchronize_rcu();
 
        pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
                 orig->htable_bits, orig, t->htable_bits, t);
-       /* If there's nobody else dumping the table, destroy it */
+       /* Add/delete elements processed by the SET target during resize.
+        * Kernel-side add cannot trigger a resize and userspace actions
+        * are serialized by the mutex.
+        */
+       list_for_each_safe(l, lt, &h->ad) {
+               x = list_entry(l, struct mtype_resize_ad, list);
+               if (x->ad == IPSET_ADD) {
+                       mtype_add(set, &x->d, &x->ext, &x->mext, x->flags);
+               } else {
+                       mtype_del(set, &x->d, NULL, NULL, 0);
+               }
+               list_del(l);
+               kfree(l);
+       }
+       /* If there's nobody else using the table, destroy it */
        if (atomic_dec_and_test(&orig->uref)) {
                pr_debug("Table destroy by resize %p\n", orig);
                mtype_ahash_destroy(set, orig, false);
@@ -677,15 +810,44 @@ out:
        return ret;
 
 cleanup:
+       rcu_read_unlock_bh();
        atomic_set(&orig->ref, 0);
        atomic_dec(&orig->uref);
-       spin_unlock_bh(&set->lock);
        mtype_ahash_destroy(set, t, false);
        if (ret == -EAGAIN)
                goto retry;
        goto out;
 }
 
+/* Get the current number of elements and ext_size in the set  */
+static void
+mtype_ext_size(struct ip_set *set, u32 *elements, size_t *ext_size)
+{
+       struct htype *h = set->data;
+       const struct htable *t;
+       u32 i, j, r;
+       struct hbucket *n;
+       struct mtype_elem *data;
+
+       t = rcu_dereference_bh(h->table);
+       for (r = 0; r < ahash_numof_locks(t->htable_bits); r++) {
+               for (i = ahash_bucket_start(r, t->htable_bits);
+                    i < ahash_bucket_end(r, t->htable_bits); i++) {
+                       n = rcu_dereference_bh(hbucket(t, i));
+                       if (!n)
+                               continue;
+                       for (j = 0; j < n->pos; j++) {
+                               if (!test_bit(j, n->used))
+                                       continue;
+                               data = ahash_data(n, j, set->dsize);
+                               if (!SET_ELEM_EXPIRED(set, data))
+                                       (*elements)++;
+                       }
+               }
+               *ext_size += t->hregion[r].ext_size;
+       }
+}
+
 /* Add an element to a hash and update the internal counters when succeeded,
  * otherwise report the proper error code.
  */
@@ -698,32 +860,49 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        const struct mtype_elem *d = value;
        struct mtype_elem *data;
        struct hbucket *n, *old = ERR_PTR(-ENOENT);
-       int i, j = -1;
+       int i, j = -1, ret;
        bool flag_exist = flags & IPSET_FLAG_EXIST;
        bool deleted = false, forceadd = false, reuse = false;
-       u32 key, multi = 0;
+       u32 r, key, multi = 0, elements, maxelem;
 
-       if (set->elements >= h->maxelem) {
-               if (SET_WITH_TIMEOUT(set))
-                       /* FIXME: when set is full, we slow down here */
-                       mtype_expire(set, h);
-               if (set->elements >= h->maxelem && SET_WITH_FORCEADD(set))
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
+       key = HKEY(value, h->initval, t->htable_bits);
+       r = ahash_region(key, t->htable_bits);
+       atomic_inc(&t->uref);
+       elements = t->hregion[r].elements;
+       maxelem = t->maxelem;
+       if (elements >= maxelem) {
+               u32 e;
+               if (SET_WITH_TIMEOUT(set)) {
+                       rcu_read_unlock_bh();
+                       mtype_gc_do(set, h, t, r);
+                       rcu_read_lock_bh();
+               }
+               maxelem = h->maxelem;
+               elements = 0;
+               for (e = 0; e < ahash_numof_locks(t->htable_bits); e++)
+                       elements += t->hregion[e].elements;
+               if (elements >= maxelem && SET_WITH_FORCEADD(set))
                        forceadd = true;
        }
+       rcu_read_unlock_bh();
 
-       t = ipset_dereference_protected(h->table, set);
-       key = HKEY(value, h->initval, t->htable_bits);
-       n = __ipset_dereference_protected(hbucket(t, key), 1);
+       spin_lock_bh(&t->hregion[r].lock);
+       n = rcu_dereference_bh(hbucket(t, key));
        if (!n) {
-               if (forceadd || set->elements >= h->maxelem)
+               if (forceadd || elements >= maxelem)
                        goto set_full;
                old = NULL;
                n = kzalloc(sizeof(*n) + AHASH_INIT_SIZE * set->dsize,
                            GFP_ATOMIC);
-               if (!n)
-                       return -ENOMEM;
+               if (!n) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
                n->size = AHASH_INIT_SIZE;
-               set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+               t->hregion[r].ext_size +=
+                       ext_size(AHASH_INIT_SIZE, set->dsize);
                goto copy_elem;
        }
        for (i = 0; i < n->pos; i++) {
@@ -737,38 +916,37 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                }
                data = ahash_data(n, i, set->dsize);
                if (mtype_data_equal(data, d, &multi)) {
-                       if (flag_exist ||
-                           (SET_WITH_TIMEOUT(set) &&
-                            ip_set_timeout_expired(ext_timeout(data, set)))) {
+                       if (flag_exist || SET_ELEM_EXPIRED(set, data)) {
                                /* Just the extensions could be overwritten */
                                j = i;
                                goto overwrite_extensions;
                        }
-                       return -IPSET_ERR_EXIST;
+                       ret = -IPSET_ERR_EXIST;
+                       goto unlock;
                }
                /* Reuse first timed out entry */
-               if (SET_WITH_TIMEOUT(set) &&
-                   ip_set_timeout_expired(ext_timeout(data, set)) &&
-                   j == -1) {
+               if (SET_ELEM_EXPIRED(set, data) && j == -1) {
                        j = i;
                        reuse = true;
                }
        }
        if (reuse || forceadd) {
+               if (j == -1)
+                       j = 0;
                data = ahash_data(n, j, set->dsize);
                if (!deleted) {
 #ifdef IP_SET_HASH_WITH_NETS
                        for (i = 0; i < IPSET_NET_COUNT; i++)
-                               mtype_del_cidr(h,
+                               mtype_del_cidr(set, h,
                                        NCIDR_PUT(DCIDR_GET(data->cidr, i)),
                                        i);
 #endif
                        ip_set_ext_destroy(set, data);
-                       set->elements--;
+                       t->hregion[r].elements--;
                }
                goto copy_data;
        }
-       if (set->elements >= h->maxelem)
+       if (elements >= maxelem)
                goto set_full;
        /* Create a new slot */
        if (n->pos >= n->size) {
@@ -776,28 +954,32 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                if (n->size >= AHASH_MAX(h)) {
                        /* Trigger rehashing */
                        mtype_data_next(&h->next, d);
-                       return -EAGAIN;
+                       ret = -EAGAIN;
+                       goto resize;
                }
                old = n;
                n = kzalloc(sizeof(*n) +
                            (old->size + AHASH_INIT_SIZE) * set->dsize,
                            GFP_ATOMIC);
-               if (!n)
-                       return -ENOMEM;
+               if (!n) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
                memcpy(n, old, sizeof(struct hbucket) +
                       old->size * set->dsize);
                n->size = old->size + AHASH_INIT_SIZE;
-               set->ext_size += ext_size(AHASH_INIT_SIZE, set->dsize);
+               t->hregion[r].ext_size +=
+                       ext_size(AHASH_INIT_SIZE, set->dsize);
        }
 
 copy_elem:
        j = n->pos++;
        data = ahash_data(n, j, set->dsize);
 copy_data:
-       set->elements++;
+       t->hregion[r].elements++;
 #ifdef IP_SET_HASH_WITH_NETS
        for (i = 0; i < IPSET_NET_COUNT; i++)
-               mtype_add_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
+               mtype_add_cidr(set, h, NCIDR_PUT(DCIDR_GET(d->cidr, i)), i);
 #endif
        memcpy(data, d, sizeof(struct mtype_elem));
 overwrite_extensions:
@@ -820,13 +1002,41 @@ overwrite_extensions:
                if (old)
                        kfree_rcu(old, rcu);
        }
+       ret = 0;
+resize:
+       spin_unlock_bh(&t->hregion[r].lock);
+       if (atomic_read(&t->ref) && ext->target) {
+               /* Resize is in process and kernel side add, save values */
+               struct mtype_resize_ad *x;
+
+               x = kzalloc(sizeof(struct mtype_resize_ad), GFP_ATOMIC);
+               if (!x)
+                       /* Don't bother */
+                       goto out;
+               x->ad = IPSET_ADD;
+               memcpy(&x->d, value, sizeof(struct mtype_elem));
+               memcpy(&x->ext, ext, sizeof(struct ip_set_ext));
+               memcpy(&x->mext, mext, sizeof(struct ip_set_ext));
+               x->flags = flags;
+               spin_lock_bh(&set->lock);
+               list_add_tail(&x->list, &h->ad);
+               spin_unlock_bh(&set->lock);
+       }
+       goto out;
 
-       return 0;
 set_full:
        if (net_ratelimit())
                pr_warn("Set %s is full, maxelem %u reached\n",
-                       set->name, h->maxelem);
-       return -IPSET_ERR_HASH_FULL;
+                       set->name, maxelem);
+       ret = -IPSET_ERR_HASH_FULL;
+unlock:
+       spin_unlock_bh(&t->hregion[r].lock);
+out:
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by add: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
+       return ret;
 }
 
 /* Delete an element from the hash and free up space if possible.
@@ -840,13 +1050,23 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        const struct mtype_elem *d = value;
        struct mtype_elem *data;
        struct hbucket *n;
-       int i, j, k, ret = -IPSET_ERR_EXIST;
+       struct mtype_resize_ad *x = NULL;
+       int i, j, k, r, ret = -IPSET_ERR_EXIST;
        u32 key, multi = 0;
        size_t dsize = set->dsize;
 
-       t = ipset_dereference_protected(h->table, set);
+       /* Userspace add and resize is excluded by the mutex.
+        * Kernespace add does not trigger resize.
+        */
+       rcu_read_lock_bh();
+       t = rcu_dereference_bh(h->table);
        key = HKEY(value, h->initval, t->htable_bits);
-       n = __ipset_dereference_protected(hbucket(t, key), 1);
+       r = ahash_region(key, t->htable_bits);
+       atomic_inc(&t->uref);
+       rcu_read_unlock_bh();
+
+       spin_lock_bh(&t->hregion[r].lock);
+       n = rcu_dereference_bh(hbucket(t, key));
        if (!n)
                goto out;
        for (i = 0, k = 0; i < n->pos; i++) {
@@ -857,8 +1077,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                data = ahash_data(n, i, dsize);
                if (!mtype_data_equal(data, d, &multi))
                        continue;
-               if (SET_WITH_TIMEOUT(set) &&
-                   ip_set_timeout_expired(ext_timeout(data, set)))
+               if (SET_ELEM_EXPIRED(set, data))
                        goto out;
 
                ret = 0;
@@ -866,20 +1085,33 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                smp_mb__after_atomic();
                if (i + 1 == n->pos)
                        n->pos--;
-               set->elements--;
+               t->hregion[r].elements--;
 #ifdef IP_SET_HASH_WITH_NETS
                for (j = 0; j < IPSET_NET_COUNT; j++)
-                       mtype_del_cidr(h, NCIDR_PUT(DCIDR_GET(d->cidr, j)),
-                                      j);
+                       mtype_del_cidr(set, h,
+                                      NCIDR_PUT(DCIDR_GET(d->cidr, j)), j);
 #endif
                ip_set_ext_destroy(set, data);
 
+               if (atomic_read(&t->ref) && ext->target) {
+                       /* Resize is in process and kernel side del,
+                        * save values
+                        */
+                       x = kzalloc(sizeof(struct mtype_resize_ad),
+                                   GFP_ATOMIC);
+                       if (x) {
+                               x->ad = IPSET_DEL;
+                               memcpy(&x->d, value,
+                                      sizeof(struct mtype_elem));
+                               x->flags = flags;
+                       }
+               }
                for (; i < n->pos; i++) {
                        if (!test_bit(i, n->used))
                                k++;
                }
                if (n->pos == 0 && k == 0) {
-                       set->ext_size -= ext_size(n->size, dsize);
+                       t->hregion[r].ext_size -= ext_size(n->size, dsize);
                        rcu_assign_pointer(hbucket(t, key), NULL);
                        kfree_rcu(n, rcu);
                } else if (k >= AHASH_INIT_SIZE) {
@@ -898,7 +1130,8 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                                k++;
                        }
                        tmp->pos = k;
-                       set->ext_size -= ext_size(AHASH_INIT_SIZE, dsize);
+                       t->hregion[r].ext_size -=
+                               ext_size(AHASH_INIT_SIZE, dsize);
                        rcu_assign_pointer(hbucket(t, key), tmp);
                        kfree_rcu(n, rcu);
                }
@@ -906,6 +1139,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        }
 
 out:
+       spin_unlock_bh(&t->hregion[r].lock);
+       if (x) {
+               spin_lock_bh(&set->lock);
+               list_add(&x->list, &h->ad);
+               spin_unlock_bh(&set->lock);
+       }
+       if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
+               pr_debug("Table destroy after resize by del: %p\n", t);
+               mtype_ahash_destroy(set, t, false);
+       }
        return ret;
 }
 
@@ -991,6 +1234,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
        int i, ret = 0;
        u32 key, multi = 0;
 
+       rcu_read_lock_bh();
        t = rcu_dereference_bh(h->table);
 #ifdef IP_SET_HASH_WITH_NETS
        /* If we test an IP address and not a network address,
@@ -1022,6 +1266,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                        goto out;
        }
 out:
+       rcu_read_unlock_bh();
        return ret;
 }
 
@@ -1033,23 +1278,14 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
        const struct htable *t;
        struct nlattr *nested;
        size_t memsize;
+       u32 elements = 0;
+       size_t ext_size = 0;
        u8 htable_bits;
 
-       /* If any members have expired, set->elements will be wrong
-        * mytype_expire function will update it with the right count.
-        * we do not hold set->lock here, so grab it first.
-        * set->elements can still be incorrect in the case of a huge set,
-        * because elements might time out during the listing.
-        */
-       if (SET_WITH_TIMEOUT(set)) {
-               spin_lock_bh(&set->lock);
-               mtype_expire(set, h);
-               spin_unlock_bh(&set->lock);
-       }
-
        rcu_read_lock_bh();
-       t = rcu_dereference_bh_nfnl(h->table);
-       memsize = mtype_ahash_memsize(h, t) + set->ext_size;
+       t = rcu_dereference_bh(h->table);
+       mtype_ext_size(set, &elements, &ext_size);
+       memsize = mtype_ahash_memsize(h, t) + ext_size + set->ext_size;
        htable_bits = t->htable_bits;
        rcu_read_unlock_bh();
 
@@ -1071,7 +1307,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
 #endif
        if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) ||
            nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
-           nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements)))
+           nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(elements)))
                goto nla_put_failure;
        if (unlikely(ip_set_put_flags(skb, set)))
                goto nla_put_failure;
@@ -1091,15 +1327,15 @@ mtype_uref(struct ip_set *set, struct netlink_callback *cb, bool start)
 
        if (start) {
                rcu_read_lock_bh();
-               t = rcu_dereference_bh_nfnl(h->table);
+               t = ipset_dereference_bh_nfnl(h->table);
                atomic_inc(&t->uref);
                cb->args[IPSET_CB_PRIVATE] = (unsigned long)t;
                rcu_read_unlock_bh();
        } else if (cb->args[IPSET_CB_PRIVATE]) {
                t = (struct htable *)cb->args[IPSET_CB_PRIVATE];
                if (atomic_dec_and_test(&t->uref) && atomic_read(&t->ref)) {
-                       /* Resizing didn't destroy the hash table */
-                       pr_debug("Table destroy by dump: %p\n", t);
+                       pr_debug("Table destroy after resize "
+                                " by dump: %p\n", t);
                        mtype_ahash_destroy(set, t, false);
                }
                cb->args[IPSET_CB_PRIVATE] = 0;
@@ -1141,8 +1377,7 @@ mtype_list(const struct ip_set *set,
                        if (!test_bit(i, n->used))
                                continue;
                        e = ahash_data(n, i, set->dsize);
-                       if (SET_WITH_TIMEOUT(set) &&
-                           ip_set_timeout_expired(ext_timeout(e, set)))
+                       if (SET_ELEM_EXPIRED(set, e))
                                continue;
                        pr_debug("list hash %lu hbucket %p i %u, data %p\n",
                                 cb->args[IPSET_CB_ARG0], n, i, e);
@@ -1208,6 +1443,7 @@ static const struct ip_set_type_variant mtype_variant = {
        .uref   = mtype_uref,
        .resize = mtype_resize,
        .same_set = mtype_same_set,
+       .region_lock = true,
 };
 
 #ifdef IP_SET_EMIT_CREATE
@@ -1226,6 +1462,7 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
        size_t hsize;
        struct htype *h;
        struct htable *t;
+       u32 i;
 
        pr_debug("Create set %s with family %s\n",
                 set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
@@ -1294,6 +1531,15 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
                kfree(h);
                return -ENOMEM;
        }
+       t->hregion = ip_set_alloc(ahash_sizeof_regions(hbits));
+       if (!t->hregion) {
+               kfree(t);
+               kfree(h);
+               return -ENOMEM;
+       }
+       h->gc.set = set;
+       for (i = 0; i < ahash_numof_locks(hbits); i++)
+               spin_lock_init(&t->hregion[i].lock);
        h->maxelem = maxelem;
 #ifdef IP_SET_HASH_WITH_NETMASK
        h->netmask = netmask;
@@ -1304,9 +1550,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
        get_random_bytes(&h->initval, sizeof(h->initval));
 
        t->htable_bits = hbits;
+       t->maxelem = h->maxelem / ahash_numof_locks(hbits);
        RCU_INIT_POINTER(h->table, t);
 
-       h->set = set;
+       INIT_LIST_HEAD(&h->ad);
        set->data = h;
 #ifndef IP_SET_PROTO_UNDEF
        if (set->family == NFPROTO_IPV4) {
@@ -1329,12 +1576,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
 #ifndef IP_SET_PROTO_UNDEF
                if (set->family == NFPROTO_IPV4)
 #endif
-                       IPSET_TOKEN(HTYPE, 4_gc_init)(set,
-                               IPSET_TOKEN(HTYPE, 4_gc));
+                       IPSET_TOKEN(HTYPE, 4_gc_init)(&h->gc);
 #ifndef IP_SET_PROTO_UNDEF
                else
-                       IPSET_TOKEN(HTYPE, 6_gc_init)(set,
-                               IPSET_TOKEN(HTYPE, 6_gc));
+                       IPSET_TOKEN(HTYPE, 6_gc_init)(&h->gc);
 #endif
        }
        pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
index 410809c..4912069 100644 (file)
@@ -411,7 +411,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                *pos = cpu + 1;
                return per_cpu_ptr(net->ct.stat, cpu);
        }
-
+       (*pos)++;
        return NULL;
 }
 
index b0930d4..b9cbe1e 100644 (file)
@@ -267,7 +267,7 @@ static void *synproxy_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                *pos = cpu + 1;
                return per_cpu_ptr(snet->stats, cpu);
        }
-
+       (*pos)++;
        return NULL;
 }
 
index d1318bd..38c680f 100644 (file)
@@ -1405,6 +1405,11 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
                                              lockdep_commit_lock_is_held(net));
                if (nft_dump_stats(skb, stats))
                        goto nla_put_failure;
+
+               if ((chain->flags & NFT_CHAIN_HW_OFFLOAD) &&
+                   nla_put_be32(skb, NFTA_CHAIN_FLAGS,
+                                htonl(NFT_CHAIN_HW_OFFLOAD)))
+                       goto nla_put_failure;
        }
 
        if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
@@ -6300,8 +6305,13 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
                goto err4;
 
        err = nft_register_flowtable_net_hooks(ctx.net, table, flowtable);
-       if (err < 0)
+       if (err < 0) {
+               list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
+                       list_del_rcu(&hook->list);
+                       kfree_rcu(hook, rcu);
+               }
                goto err4;
+       }
 
        err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
        if (err < 0)
@@ -7378,13 +7388,8 @@ static void nf_tables_module_autoload(struct net *net)
        list_splice_init(&net->nft.module_list, &module_list);
        mutex_unlock(&net->nft.commit_mutex);
        list_for_each_entry_safe(req, next, &module_list, list) {
-               if (req->done) {
-                       list_del(&req->list);
-                       kfree(req);
-               } else {
-                       request_module("%s", req->module);
-                       req->done = true;
-               }
+               request_module("%s", req->module);
+               req->done = true;
        }
        mutex_lock(&net->nft.commit_mutex);
        list_splice(&module_list, &net->nft.module_list);
@@ -8167,6 +8172,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
        __nft_release_tables(net);
        mutex_unlock(&net->nft.commit_mutex);
        WARN_ON_ONCE(!list_empty(&net->nft.tables));
+       WARN_ON_ONCE(!list_empty(&net->nft.module_list));
 }
 
 static struct pernet_operations nf_tables_net_ops = {
index de3a959..a5f294a 100644 (file)
@@ -742,6 +742,8 @@ static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = {
        [NFCTH_NAME] = { .type = NLA_NUL_STRING,
                         .len = NF_CT_HELPER_NAME_LEN-1 },
        [NFCTH_QUEUE_NUM] = { .type = NLA_U32, },
+       [NFCTH_PRIV_DATA_LEN] = { .type = NLA_U32, },
+       [NFCTH_STATUS] = { .type = NLA_U32, },
 };
 
 static const struct nfnl_callback nfnl_cthelper_cb[NFNL_MSG_CTHELPER_MAX] = {
index ff9ac8a..eac4a90 100644 (file)
@@ -89,6 +89,7 @@ static const struct nft_chain_type nft_chain_nat_inet = {
        .name           = "nat",
        .type           = NFT_CHAIN_T_NAT,
        .family         = NFPROTO_INET,
+       .owner          = THIS_MODULE,
        .hook_mask      = (1 << NF_INET_PRE_ROUTING) |
                          (1 << NF_INET_LOCAL_IN) |
                          (1 << NF_INET_LOCAL_OUT) |
index 1993af3..a7de3a5 100644 (file)
@@ -129,6 +129,7 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
        [NFTA_PAYLOAD_LEN]              = { .type = NLA_U32 },
        [NFTA_PAYLOAD_CSUM_TYPE]        = { .type = NLA_U32 },
        [NFTA_PAYLOAD_CSUM_OFFSET]      = { .type = NLA_U32 },
+       [NFTA_PAYLOAD_CSUM_FLAGS]       = { .type = NLA_U32 },
 };
 
 static int nft_payload_init(const struct nft_ctx *ctx,
index feac855..4fc0c92 100644 (file)
@@ -1766,11 +1766,13 @@ static bool pipapo_match_field(struct nft_pipapo_field *f,
 static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                              const struct nft_set_elem *elem)
 {
-       const u8 *data = (const u8 *)elem->key.val.data;
        struct nft_pipapo *priv = nft_set_priv(set);
        struct nft_pipapo_match *m = priv->clone;
+       struct nft_pipapo_elem *e = elem->priv;
        int rules_f0, first_rule = 0;
-       struct nft_pipapo_elem *e;
+       const u8 *data;
+
+       data = (const u8 *)nft_set_ext_key(&e->ext);
 
        e = pipapo_get(net, set, data, 0);
        if (IS_ERR(e))
index 4c3f2e2..764e886 100644 (file)
@@ -339,6 +339,8 @@ static const struct nla_policy nft_tunnel_key_policy[NFTA_TUNNEL_KEY_MAX + 1] =
        [NFTA_TUNNEL_KEY_FLAGS] = { .type = NLA_U32, },
        [NFTA_TUNNEL_KEY_TOS]   = { .type = NLA_U8, },
        [NFTA_TUNNEL_KEY_TTL]   = { .type = NLA_U8, },
+       [NFTA_TUNNEL_KEY_SPORT] = { .type = NLA_U16, },
+       [NFTA_TUNNEL_KEY_DPORT] = { .type = NLA_U16, },
        [NFTA_TUNNEL_KEY_OPTS]  = { .type = NLA_NESTED, },
 };
 
index e27c6c5..cd2b034 100644 (file)
@@ -1551,6 +1551,9 @@ static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos,
        uint8_t nfproto = (unsigned long)PDE_DATA(file_inode(seq->file));
        struct nf_mttg_trav *trav = seq->private;
 
+       if (ppos != NULL)
+               ++(*ppos);
+
        switch (trav->class) {
        case MTTG_TRAV_INIT:
                trav->class = MTTG_TRAV_NFP_UNSPEC;
@@ -1576,9 +1579,6 @@ static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos,
        default:
                return NULL;
        }
-
-       if (ppos != NULL)
-               ++*ppos;
        return trav;
 }
 
index 7a2c4b8..8c835ad 100644 (file)
@@ -402,15 +402,6 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo)
                remove_proc_entry(hinfo->name, parent);
 }
 
-static void htable_destroy(struct xt_hashlimit_htable *hinfo)
-{
-       cancel_delayed_work_sync(&hinfo->gc_work);
-       htable_remove_proc_entry(hinfo);
-       htable_selective_cleanup(hinfo, true);
-       kfree(hinfo->name);
-       vfree(hinfo);
-}
-
 static struct xt_hashlimit_htable *htable_find_get(struct net *net,
                                                   const char *name,
                                                   u_int8_t family)
@@ -432,8 +423,13 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
 {
        if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) {
                hlist_del(&hinfo->node);
+               htable_remove_proc_entry(hinfo);
                mutex_unlock(&hashlimit_mutex);
-               htable_destroy(hinfo);
+
+               cancel_delayed_work_sync(&hinfo->gc_work);
+               htable_selective_cleanup(hinfo, true);
+               kfree(hinfo->name);
+               vfree(hinfo);
        }
 }
 
index 0a97080..225a7ab 100644 (file)
@@ -492,12 +492,12 @@ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        const struct recent_entry *e = v;
        const struct list_head *head = e->list.next;
 
+       (*pos)++;
        while (head == &t->iphash[st->bucket]) {
                if (++st->bucket >= ip_list_hash_size)
                        return NULL;
                head = t->iphash[st->bucket].next;
        }
-       (*pos)++;
        return list_entry(head, struct recent_entry, list);
 }
 
index edf3e28..5313f1c 100644 (file)
@@ -2434,7 +2434,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
                                                               in_skb->len))
                                WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
                                                    (u8 *)extack->bad_attr -
-                                                   in_skb->data));
+                                                   (u8 *)nlh));
                } else {
                        if (extack->cookie_len)
                                WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
index 0522b2b..9f357aa 100644 (file)
@@ -497,8 +497,9 @@ genl_family_rcv_msg_attrs_parse(const struct genl_family *family,
 
        err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
                            family->policy, validate, extack);
-       if (err && parallel) {
-               kfree(attrbuf);
+       if (err) {
+               if (parallel)
+                       kfree(attrbuf);
                return ERR_PTR(err);
        }
        return attrbuf;
index 6f1b096..43811b5 100644 (file)
@@ -181,13 +181,20 @@ exit:
 void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
                          struct sk_buff *skb)
 {
-       u8 gate = hdev->pipes[pipe].gate;
        u8 status = NFC_HCI_ANY_OK;
        struct hci_create_pipe_resp *create_info;
        struct hci_delete_pipe_noti *delete_info;
        struct hci_all_pipe_cleared_noti *cleared_info;
+       u8 gate;
 
-       pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
+       pr_debug("from pipe %x cmd %x\n", pipe, cmd);
+
+       if (pipe >= NFC_HCI_MAX_PIPES) {
+               status = NFC_HCI_ANY_E_NOK;
+               goto exit;
+       }
+
+       gate = hdev->pipes[pipe].gate;
 
        switch (cmd) {
        case NFC_HCI_ADM_NOTIFY_PIPE_CREATED:
@@ -375,8 +382,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
                            struct sk_buff *skb)
 {
        int r = 0;
-       u8 gate = hdev->pipes[pipe].gate;
+       u8 gate;
+
+       if (pipe >= NFC_HCI_MAX_PIPES) {
+               pr_err("Discarded event %x to invalid pipe %x\n", event, pipe);
+               goto exit;
+       }
 
+       gate = hdev->pipes[pipe].gate;
        if (gate == NFC_HCI_INVALID_GATE) {
                pr_err("Discarded event %x to unopened pipe %x\n", event, pipe);
                goto exit;
index eee0ddd..e894254 100644 (file)
@@ -32,6 +32,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
        [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
                                .len = NFC_DEVICE_NAME_MAXSIZE },
        [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
+       [NFC_ATTR_TARGET_INDEX] = { .type = NLA_U32 },
        [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
        [NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
        [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
@@ -43,7 +44,10 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
        [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED },
        [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING,
                                     .len = NFC_FIRMWARE_NAME_MAXSIZE },
+       [NFC_ATTR_SE_INDEX] = { .type = NLA_U32 },
        [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY },
+       [NFC_ATTR_VENDOR_ID] = { .type = NLA_U32 },
+       [NFC_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 },
        [NFC_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
 
 };
index c047afd..07a7dd1 100644 (file)
@@ -645,6 +645,7 @@ static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {
        [OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },
        [OVS_PACKET_ATTR_PROBE] = { .type = NLA_FLAG },
        [OVS_PACKET_ATTR_MRU] = { .type = NLA_U16 },
+       [OVS_PACKET_ATTR_HASH] = { .type = NLA_U64 },
 };
 
 static const struct genl_ops dp_packet_genl_ops[] = {
index 30c6879..e5b0986 100644 (file)
@@ -2274,6 +2274,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                                        TP_STATUS_KERNEL, (macoff+snaplen));
        if (!h.raw)
                goto drop_n_account;
+
+       if (do_vnet &&
+           virtio_net_hdr_from_skb(skb, h.raw + macoff -
+                                   sizeof(struct virtio_net_hdr),
+                                   vio_le(), true, 0))
+               goto drop_n_account;
+
        if (po->tp_version <= TPACKET_V2) {
                packet_increment_rx_head(po, &po->rx_ring);
        /*
@@ -2286,12 +2293,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
                        status |= TP_STATUS_LOSING;
        }
 
-       if (do_vnet &&
-           virtio_net_hdr_from_skb(skb, h.raw + macoff -
-                                   sizeof(struct virtio_net_hdr),
-                                   vio_le(), true, 0))
-               goto drop_n_account;
-
        po->stats.stats1.tp_packets++;
        if (copy_skb) {
                status |= TP_STATUS_COPY;
index 90a31b1..8c466a7 100644 (file)
@@ -186,6 +186,7 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
                + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
                + cookie_len /* TCA_ACT_COOKIE */
                + nla_total_size(0) /* TCA_ACT_STATS nested */
+               + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */
                /* TCA_STATS_BASIC */
                + nla_total_size_64bit(sizeof(struct gnet_stats_basic))
                /* TCA_STATS_PKT64 */
index a5a2954..371ad84 100644 (file)
@@ -744,6 +744,7 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
        [TCA_FQ_FLOW_MAX_RATE]          = { .type = NLA_U32 },
        [TCA_FQ_BUCKETS_LOG]            = { .type = NLA_U32 },
        [TCA_FQ_FLOW_REFILL_DELAY]      = { .type = NLA_U32 },
+       [TCA_FQ_ORPHAN_MASK]            = { .type = NLA_U32 },
        [TCA_FQ_LOW_RATE_THRESHOLD]     = { .type = NLA_U32 },
        [TCA_FQ_CE_THRESHOLD]           = { .type = NLA_U32 },
 };
index 660fc45..b1eb12d 100644 (file)
@@ -564,8 +564,10 @@ static struct sk_buff *taprio_dequeue_soft(struct Qdisc *sch)
                prio = skb->priority;
                tc = netdev_get_prio_tc_map(dev, prio);
 
-               if (!(gate_mask & BIT(tc)))
+               if (!(gate_mask & BIT(tc))) {
+                       skb = NULL;
                        continue;
+               }
 
                len = qdisc_pkt_len(skb);
                guard = ktime_add_ns(taprio_get_time(q),
@@ -575,13 +577,17 @@ static struct sk_buff *taprio_dequeue_soft(struct Qdisc *sch)
                 * guard band ...
                 */
                if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
-                   ktime_after(guard, entry->close_time))
+                   ktime_after(guard, entry->close_time)) {
+                       skb = NULL;
                        continue;
+               }
 
                /* ... and no budget. */
                if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
-                   atomic_sub_return(len, &entry->budget) < 0)
+                   atomic_sub_return(len, &entry->budget) < 0) {
+                       skb = NULL;
                        continue;
+               }
 
                skb = child->ops->dequeue(child);
                if (unlikely(!skb))
@@ -768,6 +774,7 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_FLAGS]                      = { .type = NLA_U32 },
+       [TCA_TAPRIO_ATTR_TXTIME_DELAY]               = { .type = NLA_U32 },
 };
 
 static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
index 8a15146..1069d7a 100644 (file)
@@ -237,15 +237,11 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
                addrcnt++;
 
        return    nla_total_size(sizeof(struct sctp_info))
-               + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
-               + nla_total_size(1) /* INET_DIAG_TOS */
-               + nla_total_size(1) /* INET_DIAG_TCLASS */
-               + nla_total_size(4) /* INET_DIAG_MARK */
-               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(addrlen * asoc->peer.transport_count)
                + nla_total_size(addrlen * addrcnt)
-               + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(sizeof(struct inet_diag_msg))
+               + inet_diag_msg_attrs_size()
+               + nla_total_size(sizeof(struct inet_diag_meminfo))
                + 64;
 }
 
index 90988a5..6fd44bd 100644 (file)
@@ -512,15 +512,18 @@ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code)
 static int smc_connect_abort(struct smc_sock *smc, int reason_code,
                             int local_contact)
 {
+       bool is_smcd = smc->conn.lgr->is_smcd;
+
        if (local_contact == SMC_FIRST_CONTACT)
-               smc_lgr_forget(smc->conn.lgr);
-       if (smc->conn.lgr->is_smcd)
+               smc_lgr_cleanup_early(&smc->conn);
+       else
+               smc_conn_free(&smc->conn);
+       if (is_smcd)
                /* there is only one lgr role for SMC-D; use server lock */
                mutex_unlock(&smc_server_lgr_pending);
        else
                mutex_unlock(&smc_client_lgr_pending);
 
-       smc_conn_free(&smc->conn);
        smc->connect_nonblock = 0;
        return reason_code;
 }
@@ -1091,7 +1094,6 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
        if (newsmcsk->sk_state == SMC_INIT)
                sock_put(&new_smc->sk); /* passive closing */
        newsmcsk->sk_state = SMC_CLOSED;
-       smc_conn_free(&new_smc->conn);
 
        smc_listen_out(new_smc);
 }
@@ -1102,12 +1104,13 @@ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
 {
        /* RDMA setup failed, switch back to TCP */
        if (local_contact == SMC_FIRST_CONTACT)
-               smc_lgr_forget(new_smc->conn.lgr);
+               smc_lgr_cleanup_early(&new_smc->conn);
+       else
+               smc_conn_free(&new_smc->conn);
        if (reason_code < 0) { /* error, no fallback possible */
                smc_listen_out_err(new_smc);
                return;
        }
-       smc_conn_free(&new_smc->conn);
        smc_switch_to_fallback(new_smc);
        new_smc->fallback_rsn = reason_code;
        if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) {
@@ -1170,16 +1173,18 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
                            new_smc->conn.lgr->vlan_id,
                            new_smc->conn.lgr->smcd)) {
                if (ini->cln_first_contact == SMC_FIRST_CONTACT)
-                       smc_lgr_forget(new_smc->conn.lgr);
-               smc_conn_free(&new_smc->conn);
+                       smc_lgr_cleanup_early(&new_smc->conn);
+               else
+                       smc_conn_free(&new_smc->conn);
                return SMC_CLC_DECL_SMCDNOTALK;
        }
 
        /* Create send and receive buffers */
        if (smc_buf_create(new_smc, true)) {
                if (ini->cln_first_contact == SMC_FIRST_CONTACT)
-                       smc_lgr_forget(new_smc->conn.lgr);
-               smc_conn_free(&new_smc->conn);
+                       smc_lgr_cleanup_early(&new_smc->conn);
+               else
+                       smc_conn_free(&new_smc->conn);
                return SMC_CLC_DECL_MEM;
        }
 
index 2249de5..5b085ef 100644 (file)
@@ -162,6 +162,18 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
        conn->lgr = NULL;
 }
 
+void smc_lgr_cleanup_early(struct smc_connection *conn)
+{
+       struct smc_link_group *lgr = conn->lgr;
+
+       if (!lgr)
+               return;
+
+       smc_conn_free(conn);
+       smc_lgr_forget(lgr);
+       smc_lgr_schedule_free_work_fast(lgr);
+}
+
 /* Send delete link, either as client to request the initiation
  * of the DELETE LINK sequence from server; or as server to
  * initiate the delete processing. See smc_llc_rx_delete_link().
index c472e12..234ae25 100644 (file)
@@ -296,6 +296,7 @@ struct smc_clc_msg_accept_confirm;
 struct smc_clc_msg_local;
 
 void smc_lgr_forget(struct smc_link_group *lgr);
+void smc_lgr_cleanup_early(struct smc_connection *conn);
 void smc_lgr_terminate(struct smc_link_group *lgr, bool soft);
 void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
 void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
@@ -316,7 +317,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, struct smc_init_info *ini);
 
 void smc_conn_free(struct smc_connection *conn);
 int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini);
-void smcd_conn_free(struct smc_connection *conn);
 void smc_lgr_schedule_free_work_fast(struct smc_link_group *lgr);
 int smc_core_init(void);
 void smc_core_exit(void);
index 5486326..05b825b 100644 (file)
@@ -573,6 +573,8 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data)
        struct smc_ib_device *smcibdev;
 
        smcibdev = ib_get_client_data(ibdev, &smc_ib_client);
+       if (!smcibdev || smcibdev->ibdev != ibdev)
+               return;
        ib_set_client_data(ibdev, &smc_ib_client, NULL);
        spin_lock(&smc_ib_devices.lock);
        list_del_init(&smcibdev->list); /* remove from smc_ib_devices */
@@ -580,6 +582,7 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data)
        smc_smcr_terminate_all(smcibdev);
        smc_ib_cleanup_per_ibdev(smcibdev);
        ib_unregister_event_handler(&smcibdev->event_handler);
+       cancel_work_sync(&smcibdev->port_event_work);
        kfree(smcibdev);
 }
 
index 7c35094..bb98624 100644 (file)
@@ -116,6 +116,7 @@ const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
        [TIPC_NLA_PROP_PRIO]            = { .type = NLA_U32 },
        [TIPC_NLA_PROP_TOL]             = { .type = NLA_U32 },
        [TIPC_NLA_PROP_WIN]             = { .type = NLA_U32 },
+       [TIPC_NLA_PROP_MTU]             = { .type = NLA_U32 },
        [TIPC_NLA_PROP_BROADCAST]       = { .type = NLA_U32 },
        [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 }
 };
index 62c12cb..68debcb 100644 (file)
@@ -682,6 +682,7 @@ static int unix_set_peek_off(struct sock *sk, int val)
        return 0;
 }
 
+#ifdef CONFIG_PROC_FS
 static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
 {
        struct sock *sk = sock->sk;
@@ -692,6 +693,9 @@ static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
                seq_printf(m, "scm_fds: %u\n", READ_ONCE(u->scm_stat.nr_fds));
        }
 }
+#else
+#define unix_show_fdinfo NULL
+#endif
 
 static const struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
index 9c5b2a9..a5f2870 100644 (file)
@@ -451,6 +451,12 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
                if (vsk->transport == new_transport)
                        return 0;
 
+               /* transport->release() must be called with sock lock acquired.
+                * This path can only be taken during vsock_stream_connect(),
+                * where we have already held the sock lock.
+                * In the other cases, this function is called on a new socket
+                * which is not assigned to any transport.
+                */
                vsk->transport->release(vsk);
                vsock_deassign_transport(vsk);
        }
@@ -753,20 +759,18 @@ static void __vsock_release(struct sock *sk, int level)
                vsk = vsock_sk(sk);
                pending = NULL; /* Compiler warning. */
 
-               /* The release call is supposed to use lock_sock_nested()
-                * rather than lock_sock(), if a sock lock should be acquired.
-                */
-               if (vsk->transport)
-                       vsk->transport->release(vsk);
-               else if (sk->sk_type == SOCK_STREAM)
-                       vsock_remove_sock(vsk);
-
                /* When "level" is SINGLE_DEPTH_NESTING, use the nested
                 * version to avoid the warning "possible recursive locking
                 * detected". When "level" is 0, lock_sock_nested(sk, level)
                 * is the same as lock_sock(sk).
                 */
                lock_sock_nested(sk, level);
+
+               if (vsk->transport)
+                       vsk->transport->release(vsk);
+               else if (sk->sk_type == SOCK_STREAM)
+                       vsock_remove_sock(vsk);
+
                sock_orphan(sk);
                sk->sk_shutdown = SHUTDOWN_MASK;
 
index 3492c02..630b851 100644 (file)
@@ -526,12 +526,9 @@ static bool hvs_close_lock_held(struct vsock_sock *vsk)
 
 static void hvs_release(struct vsock_sock *vsk)
 {
-       struct sock *sk = sk_vsock(vsk);
        bool remove_sock;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        remove_sock = hvs_close_lock_held(vsk);
-       release_sock(sk);
        if (remove_sock)
                vsock_remove_sock(vsk);
 }
index d9f0c9c..f3c4bab 100644 (file)
@@ -829,7 +829,6 @@ void virtio_transport_release(struct vsock_sock *vsk)
        struct sock *sk = &vsk->sk;
        bool remove_sock = true;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
        if (sk->sk_type == SOCK_STREAM)
                remove_sock = virtio_transport_close(vsk);
 
@@ -837,7 +836,6 @@ void virtio_transport_release(struct vsock_sock *vsk)
                list_del(&pkt->list);
                virtio_transport_free_pkt(pkt);
        }
-       release_sock(sk);
 
        if (remove_sock)
                vsock_remove_sock(vsk);
index cedf17d..ec5d677 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/netlink.h>
 #include <linux/nospec.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <net/net_namespace.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
@@ -469,6 +470,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
        [NL80211_ATTR_STA_PLINK_STATE] =
                NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1),
+       [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 },
+       [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG },
        [NL80211_ATTR_MESH_PEER_AID] =
                NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
        [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
@@ -530,6 +533,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MDID] = { .type = NLA_U16 },
        [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
                                  .len = IEEE80211_MAX_DATA_LEN },
+       [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 },
+       [NL80211_ATTR_MAX_CRIT_PROT_DURATION] = { .type = NLA_U16 },
        [NL80211_ATTR_PEER_AID] =
                NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID),
        [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
@@ -560,6 +565,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
                NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1),
        [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
        [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
+       [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 },
        [NL80211_ATTR_MAC_MASK] = {
                .type = NLA_EXACT_LEN_WARN,
                .len = ETH_ALEN
@@ -4800,8 +4806,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                err = nl80211_parse_he_obss_pd(
                                        info->attrs[NL80211_ATTR_HE_OBSS_PD],
                                        &params.he_obss_pd);
-               if (err)
-                       return err;
+               goto out;
        }
 
        nl80211_calculate_ap_params(&params);
@@ -4823,6 +4828,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
        }
        wdev_unlock(wdev);
 
+out:
        kfree(params.acl);
 
        return err;
index fff9a74..1a8218f 100644 (file)
@@ -2276,7 +2276,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
                        break;
        }
 
-       if (IS_ERR(reg_rule)) {
+       if (IS_ERR_OR_NULL(reg_rule)) {
                pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n",
                         chan->center_freq);
                if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
index bae6254..752ff0a 100644 (file)
@@ -300,15 +300,15 @@ DT_BINDING_DIR := Documentation/devicetree/bindings
 DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml
 
 quiet_cmd_dtb_check =  CHECK   $@
-      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ ;
+      cmd_dtb_check =  $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
 
-define rule_dtc_dt_yaml
+define rule_dtc
        $(call cmd_and_fixdep,dtc,yaml)
        $(call cmd,dtb_check)
 endef
 
 $(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
-       $(call if_changed_rule,dtc_dt_yaml)
+       $(call if_changed_rule,dtc)
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
old mode 100644 (file)
new mode 100755 (executable)
index 9f60a50..5bf1ea1 100644 (file)
@@ -649,8 +649,6 @@ snd_sgio2audio_pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = {
        .open =        snd_sgio2audio_playback1_open,
        .close =       snd_sgio2audio_pcm_close,
-       .hw_params =   snd_sgio2audio_pcm_hw_params,
-       .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
        .trigger =     snd_sgio2audio_pcm_trigger,
        .pointer =     snd_sgio2audio_pcm_pointer,
@@ -659,8 +657,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = {
 static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = {
        .open =        snd_sgio2audio_playback2_open,
        .close =       snd_sgio2audio_pcm_close,
-       .hw_params =   snd_sgio2audio_pcm_hw_params,
-       .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
        .trigger =     snd_sgio2audio_pcm_trigger,
        .pointer =     snd_sgio2audio_pcm_pointer,
@@ -669,8 +665,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = {
 static const struct snd_pcm_ops snd_sgio2audio_capture_ops = {
        .open =        snd_sgio2audio_capture_open,
        .close =       snd_sgio2audio_pcm_close,
-       .hw_params =   snd_sgio2audio_pcm_hw_params,
-       .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
        .trigger =     snd_sgio2audio_pcm_trigger,
        .pointer =     snd_sgio2audio_pcm_pointer,
index 477589e..0ac06ff 100644 (file)
@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
@@ -5920,7 +5921,8 @@ enum {
        ALC289_FIXUP_DUAL_SPK,
        ALC294_FIXUP_SPK2_TO_DAC1,
        ALC294_FIXUP_ASUS_DUAL_SPK,
-
+       ALC285_FIXUP_THINKPAD_HEADSET_JACK,
+       ALC294_FIXUP_ASUS_HPE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6684,6 +6686,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC285_FIXUP_SPEAKER2_TO_DAC1] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
        },
        [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = {
                .type = HDA_FIXUP_PINS,
@@ -7040,7 +7044,23 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC294_FIXUP_SPK2_TO_DAC1
        },
-
+       [ALC285_FIXUP_THINKPAD_HEADSET_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_jack,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1
+       },
+       [ALC294_FIXUP_ASUS_HPE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Set EAPD high */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7115,6 +7135,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
        SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
+       SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -7204,6 +7226,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
@@ -7274,8 +7297,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
-       SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
+       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
+       SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
index 7e90f5d..ea91243 100644 (file)
@@ -1406,7 +1406,7 @@ config SND_SOC_WM8737
        depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8741
-       tristate "Wolfson Microelectronics WM8737 DAC"
+       tristate "Wolfson Microelectronics WM8741 DAC"
        depends on SND_SOC_I2C_AND_SPI
 
 config SND_SOC_WM8750
index 861210f..4cbef9a 100644 (file)
@@ -1564,13 +1564,15 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap)
        }
 
        pcm512x->sclk = devm_clk_get(dev, NULL);
-       if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
+       if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto err;
+       }
        if (!IS_ERR(pcm512x->sclk)) {
                ret = clk_prepare_enable(pcm512x->sclk);
                if (ret != 0) {
                        dev_err(dev, "Failed to enable SCLK: %d\n", ret);
-                       return ret;
+                       goto err;
                }
        }
 
index 6d490e2..66eb55b 100644 (file)
@@ -664,7 +664,7 @@ static int rt1015_hw_params(struct snd_pcm_substream *substream,
        snd_soc_component_update_bits(component, RT1015_TDM_MASTER,
                RT1015_I2S_DL_MASK, val_len);
        snd_soc_component_update_bits(component, RT1015_CLK2,
-               RT1015_FS_PD_MASK, pre_div);
+               RT1015_FS_PD_MASK, pre_div << RT1015_FS_PD_SFT);
 
        return 0;
 }
@@ -857,6 +857,7 @@ struct snd_soc_dai_driver rt1015_dai[] = {
                        .rates = RT1015_STEREO_RATES,
                        .formats = RT1015_FORMATS,
                },
+               .ops = &rt1015_aif_dai_ops,
        }
 };
 
index 729acd8..be52886 100644 (file)
@@ -215,7 +215,8 @@ static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth)
                break;
 
        default:
-               dev_info(tas2562->dev, "Not supported params format\n");
+               dev_info(tas2562->dev, "Unsupported bitwidth format\n");
+               return -EINVAL;
        }
 
        ret = snd_soc_component_update_bits(tas2562->component,
@@ -251,7 +252,7 @@ static int tas2562_hw_params(struct snd_pcm_substream *substream,
 
        ret = tas2562_set_samplerate(tas2562, params_rate(params));
        if (ret)
-               dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
+               dev_err(tas2562->dev, "set sample rate failed, %d\n", ret);
 
        return ret;
 }
index 3466675..a15aa2f 100644 (file)
@@ -34,8 +34,8 @@ static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf,
        int i;
        ssize_t ret = 0;
 
-       for (i = 0; i < max_pin; i++)
-               ret += snprintf(buf + size, MOD_BUF - size,
+       for (i = 0; i < max_pin; i++) {
+               ret += scnprintf(buf + size, MOD_BUF - size,
                                "%s %d\n\tModule %d\n\tInstance %d\n\t"
                                "In-used %s\n\tType %s\n"
                                "\tState %d\n\tIndex %d\n",
@@ -45,13 +45,15 @@ static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf,
                                m_pin[i].in_use ? "Used" : "Unused",
                                m_pin[i].is_dynamic ? "Dynamic" : "Static",
                                m_pin[i].pin_state, i);
+               size += ret;
+       }
        return ret;
 }
 
 static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf,
                                        ssize_t size, bool direction)
 {
-       return snprintf(buf + size, MOD_BUF - size,
+       return scnprintf(buf + size, MOD_BUF - size,
                        "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t"
                        "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t"
                        "Sample Type %d\n\tCh Map %#x\n",
@@ -75,16 +77,16 @@ static ssize_t module_read(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
-       ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n"
+       ret = scnprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n"
                        "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid,
                        mconfig->id.module_id, mconfig->id.instance_id,
                        mconfig->id.pvt_id);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n",
                        res->cpc, res->ibs, res->obs);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Module data:\n\tCore %d\n\tIn queue %d\n\t"
                        "Out queue %d\n\tType %s\n",
                        mconfig->core_id, mconfig->max_in_queue,
@@ -94,38 +96,38 @@ static ssize_t module_read(struct file *file, char __user *user_buf,
        ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true);
        ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Fixup:\n\tParams %#x\n\tConverter %#x\n",
                        mconfig->params_fixup, mconfig->converter);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n",
                        mconfig->dev_type, mconfig->vbus_id,
                        mconfig->hw_conn_type, mconfig->time_slot);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t"
                        "Pages %#x\n", mconfig->pipe->ppl_id,
                        mconfig->pipe->pipe_priority, mconfig->pipe->conn_type,
                        mconfig->pipe->memory_pages);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n",
                        mconfig->pipe->p_params->host_dma_id,
                        mconfig->pipe->p_params->link_dma_id);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n",
                        mconfig->pipe->p_params->ch,
                        mconfig->pipe->p_params->s_freq,
                        mconfig->pipe->p_params->s_fmt);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "\tLink %#x\n\tStream %#x\n",
                        mconfig->pipe->p_params->linktype,
                        mconfig->pipe->p_params->stream);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "\tState %d\n\tPassthru %s\n",
                        mconfig->pipe->state,
                        mconfig->pipe->passthru ? "true" : "false");
@@ -135,7 +137,7 @@ static ssize_t module_read(struct file *file, char __user *user_buf,
        ret += skl_print_pins(mconfig->m_out_pin, buf,
                        mconfig->max_out_queue, ret, false);
 
-       ret += snprintf(buf + ret, MOD_BUF - ret,
+       ret += scnprintf(buf + ret, MOD_BUF - ret,
                        "Other:\n\tDomain %d\n\tHomogeneous Input %s\n\t"
                        "Homogeneous Output %s\n\tIn Queue Mask %d\n\t"
                        "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t"
@@ -191,7 +193,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf,
                __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2);
 
        for (offset = 0; offset < FW_REG_SIZE; offset += 16) {
-               ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
+               ret += scnprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset);
                hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4,
                                   tmp + ret, FW_REG_BUF - ret, 0);
                ret += strlen(tmp + ret);
index 1c0e522..bd43885 100644 (file)
@@ -384,9 +384,11 @@ static int skl_clk_dev_probe(struct platform_device *pdev)
                                &clks[i], clk_pdata, i);
 
                if (IS_ERR(data->clk[data->avail_clk_cnt])) {
-                       ret = PTR_ERR(data->clk[data->avail_clk_cnt++]);
+                       ret = PTR_ERR(data->clk[data->avail_clk_cnt]);
                        goto err_unreg_skl_clk;
                }
+
+               data->avail_clk_cnt++;
        }
 
        platform_set_drvdata(pdev, data);
index 9cfbd34..8a0db28 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <sound/pcm_params.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 #include <sound/soc.h>
 #include <sound/soc-dai.h>
 
@@ -378,6 +379,11 @@ static int g12a_tohdmitx_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        void __iomem *regs;
        struct regmap *map;
+       int ret;
+
+       ret = device_reset(dev);
+       if (ret)
+               return ret;
 
        regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(regs))
index 14e175c..785a038 100644 (file)
@@ -451,7 +451,7 @@ int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
        int i, ret;
 
        for_each_rtd_components(rtd, i, component) {
-               if (component->driver->ioctl) {
+               if (component->driver->sync_stop) {
                        ret = component->driver->sync_stop(component,
                                                           substream);
                        if (ret < 0)
index 223cd04..392a1c5 100644 (file)
@@ -299,7 +299,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
        for_each_dpcm_be(fe, stream, dpcm)
                dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 
-       snd_soc_dapm_stream_stop(fe, stream);
+       dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
index 9b13056..9fb54e6 100644 (file)
@@ -4772,7 +4772,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm)
                        continue;
                if (w->power) {
                        dapm_seq_insert(w, &down_list, false);
-                       w->power = 0;
+                       w->new_power = 0;
                        powerdown = 1;
                }
        }
index ff1b7c7..2c59b36 100644 (file)
@@ -2006,7 +2006,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
        soc_pcm_close(substream);
 
        /* run the stream event for each BE */
-       snd_soc_dapm_stream_stop(fe, stream);
+       dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
        dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
@@ -3171,16 +3171,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
        unsigned long flags;
 
        /* FE state */
-       offset += snprintf(buf + offset, size - offset,
+       offset += scnprintf(buf + offset, size - offset,
                        "[%s - %s]\n", fe->dai_link->name,
                        stream ? "Capture" : "Playback");
 
-       offset += snprintf(buf + offset, size - offset, "State: %s\n",
+       offset += scnprintf(buf + offset, size - offset, "State: %s\n",
                        dpcm_state_string(fe->dpcm[stream].state));
 
        if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
            (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
-               offset += snprintf(buf + offset, size - offset,
+               offset += scnprintf(buf + offset, size - offset,
                                "Hardware Params: "
                                "Format = %s, Channels = %d, Rate = %d\n",
                                snd_pcm_format_name(params_format(params)),
@@ -3188,10 +3188,10 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
                                params_rate(params));
 
        /* BEs state */
-       offset += snprintf(buf + offset, size - offset, "Backends:\n");
+       offset += scnprintf(buf + offset, size - offset, "Backends:\n");
 
        if (list_empty(&fe->dpcm[stream].be_clients)) {
-               offset += snprintf(buf + offset, size - offset,
+               offset += scnprintf(buf + offset, size - offset,
                                " No active DSP links\n");
                goto out;
        }
@@ -3201,16 +3201,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
                struct snd_soc_pcm_runtime *be = dpcm->be;
                params = &dpcm->hw_params;
 
-               offset += snprintf(buf + offset, size - offset,
+               offset += scnprintf(buf + offset, size - offset,
                                "- %s\n", be->dai_link->name);
 
-               offset += snprintf(buf + offset, size - offset,
+               offset += scnprintf(buf + offset, size - offset,
                                "   State: %s\n",
                                dpcm_state_string(be->dpcm[stream].state));
 
                if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP))
-                       offset += snprintf(buf + offset, size - offset,
+                       offset += scnprintf(buf + offset, size - offset,
                                "   Hardware Params: "
                                "Format = %s, Channels = %d, Rate = %d\n",
                                snd_pcm_format_name(params_format(params)),
index d2ee6ad..575da6a 100644 (file)
@@ -2377,8 +2377,11 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg,
                }
 
                ret = soc_tplg_link_config(tplg, _link);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (!abi_match)
+                               kfree(_link);
                        return ret;
+               }
 
                /* offset by version-specific struct size and
                 * real priv data size
@@ -2542,7 +2545,7 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
 {
        struct snd_soc_tplg_manifest *manifest, *_manifest;
        bool abi_match;
-       int err;
+       int ret = 0;
 
        if (tplg->pass != SOC_TPLG_PASS_MANIFEST)
                return 0;
@@ -2555,19 +2558,19 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg,
                _manifest = manifest;
        } else {
                abi_match = false;
-               err = manifest_new_ver(tplg, manifest, &_manifest);
-               if (err < 0)
-                       return err;
+               ret = manifest_new_ver(tplg, manifest, &_manifest);
+               if (ret < 0)
+                       return ret;
        }
 
        /* pass control to component driver for optional further init */
        if (tplg->comp && tplg->ops && tplg->ops->manifest)
-               return tplg->ops->manifest(tplg->comp, tplg->index, _manifest);
+               ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest);
 
        if (!abi_match) /* free the duplicated one */
                kfree(_manifest);
 
-       return 0;
+       return ret;
 }
 
 /* validate header magic, size and type */
index b63fc52..78aa1da 100644 (file)
@@ -499,7 +499,7 @@ int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
 
        /* send IPC to the DSP */
        err = sof_ipc_tx_message(sdev->ipc,
-                                stream.hdr.cmd, &stream, sizeof(stream), &posn,
+                                stream.hdr.cmd, &stream, sizeof(stream), posn,
                                 sizeof(*posn));
        if (err < 0) {
                dev_err(sdev->dev, "error: failed to get stream %d position\n",
index 30bcd5d..10eb4b8 100644 (file)
@@ -1543,20 +1543,20 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = devm_snd_soc_register_component(&pdev->dev, &stm32_component,
-                                             &sai->cpu_dai_drv, 1);
+       ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not register pcm dma\n");
+               return ret;
+       }
+
+       ret = snd_soc_register_component(&pdev->dev, &stm32_component,
+                                        &sai->cpu_dai_drv, 1);
        if (ret)
                return ret;
 
        if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
                conf = &stm32_sai_pcm_config_spdif;
 
-       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
-       if (ret) {
-               dev_err(&pdev->dev, "Could not register pcm dma\n");
-               return ret;
-       }
-
        return 0;
 }
 
@@ -1565,6 +1565,8 @@ static int stm32_sai_sub_remove(struct platform_device *pdev)
        struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev);
 
        clk_unprepare(sai->pdata->pclk);
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
 
        return 0;
 }
index ebe1685..d5e517d 100644 (file)
 #define MSR_K7_HWCR                    0xc0010015
 #define MSR_K7_HWCR_SMMLOCK_BIT                0
 #define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_HWCR_IRPERF_EN_BIT      30
+#define MSR_K7_HWCR_IRPERF_EN          BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
 #define MSR_K7_FID_VID_CTL             0xc0010041
 #define MSR_K7_FID_VID_STATUS          0xc0010042
 
index 503d3f4..3f3f780 100644 (file)
@@ -390,6 +390,7 @@ struct kvm_sync_regs {
 #define KVM_STATE_NESTED_GUEST_MODE    0x00000001
 #define KVM_STATE_NESTED_RUN_PENDING   0x00000002
 #define KVM_STATE_NESTED_EVMCS         0x00000004
+#define KVM_STATE_NESTED_MTF_PENDING   0x00000008
 
 #define KVM_STATE_NESTED_SMM_GUEST_MODE        0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON     0x00000002
index e978a63..036e667 100644 (file)
@@ -4,10 +4,7 @@
 
 #include <stdio.h>
 
-/* controllable printf */
-extern int pr_output;
-#define printk(fmt, ...)       \
-       (pr_output ? printf(fmt, ##__VA_ARGS__) : 0)
+#define printk(fmt, ...) printf(fmt, ##__VA_ARGS__)
 
 #define pr_err printk
 #define pr_warn        printk
index e18eeb0..a9b9781 100644 (file)
@@ -14,8 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/bootconfig.h>
 
-int pr_output = 1;
-
 static int xbc_show_array(struct xbc_node *node)
 {
        const char *val;
@@ -131,15 +129,26 @@ int load_xbc_from_initrd(int fd, char **buf)
        struct stat stat;
        int ret;
        u32 size = 0, csum = 0, rcsum;
+       char magic[BOOTCONFIG_MAGIC_LEN];
 
        ret = fstat(fd, &stat);
        if (ret < 0)
                return -errno;
 
-       if (stat.st_size < 8)
+       if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
+               return 0;
+
+       if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
+               pr_err("Failed to lseek: %d\n", -errno);
+               return -errno;
+       }
+       if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
+               return -errno;
+       /* Check the bootconfig magic bytes */
+       if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
                return 0;
 
-       if (lseek(fd, -8, SEEK_END) < 0) {
+       if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -150,11 +159,14 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (read(fd, &csum, sizeof(u32)) < 0)
                return -errno;
 
-       /* Wrong size, maybe no boot config here */
-       if (stat.st_size < size + 8)
-               return 0;
+       /* Wrong size error  */
+       if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
+               pr_err("bootconfig size is too big\n");
+               return -E2BIG;
+       }
 
-       if (lseek(fd, stat.st_size - 8 - size, SEEK_SET) < 0) {
+       if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
+                 SEEK_SET) < 0) {
                pr_err("Failed to lseek: %d\n", -errno);
                return -errno;
        }
@@ -163,17 +175,17 @@ int load_xbc_from_initrd(int fd, char **buf)
        if (ret < 0)
                return ret;
 
-       /* Wrong Checksum, maybe no boot config here */
+       /* Wrong Checksum */
        rcsum = checksum((unsigned char *)*buf, size);
        if (csum != rcsum) {
                pr_err("checksum error: %d != %d\n", csum, rcsum);
-               return 0;
+               return -EINVAL;
        }
 
        ret = xbc_init(*buf);
-       /* Wrong data, maybe no boot config here */
+       /* Wrong data */
        if (ret < 0)
-               return 0;
+               return ret;
 
        return size;
 }
@@ -213,20 +225,15 @@ int delete_xbc(const char *path)
                return -errno;
        }
 
-       /*
-        * Suppress error messages in xbc_init() because it can be just a
-        * data which concidentally matches the size and checksum footer.
-        */
-       pr_output = 0;
        size = load_xbc_from_initrd(fd, &buf);
-       pr_output = 1;
        if (size < 0) {
                ret = size;
                pr_err("Failed to load a boot config from initrd: %d\n", ret);
        } else if (size > 0) {
                ret = fstat(fd, &stat);
                if (!ret)
-                       ret = ftruncate(fd, stat.st_size - size - 8);
+                       ret = ftruncate(fd, stat.st_size
+                                       - size - 8 - BOOTCONFIG_MAGIC_LEN);
                if (ret)
                        ret = -errno;
        } /* Ignore if there is no boot config in initrd */
@@ -295,6 +302,12 @@ int apply_xbc(const char *path, const char *xbc_path)
                pr_err("Failed to apply a boot config: %d\n", ret);
                return ret;
        }
+       /* Write a magic word of the bootconfig */
+       ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
+       if (ret < 0) {
+               pr_err("Failed to apply a boot config magic: %d\n", ret);
+               return ret;
+       }
        close(fd);
        free(data);
 
diff --git a/tools/bootconfig/samples/bad-mixed-kv1.bconf b/tools/bootconfig/samples/bad-mixed-kv1.bconf
new file mode 100644 (file)
index 0000000..1761547
--- /dev/null
@@ -0,0 +1,3 @@
+# value -> subkey pattern
+key = value
+key.subkey = another-value
diff --git a/tools/bootconfig/samples/bad-mixed-kv2.bconf b/tools/bootconfig/samples/bad-mixed-kv2.bconf
new file mode 100644 (file)
index 0000000..6b32e0c
--- /dev/null
@@ -0,0 +1,3 @@
+# subkey -> value pattern
+key.subkey = value
+key = another-value
diff --git a/tools/bootconfig/samples/bad-samekey.bconf b/tools/bootconfig/samples/bad-samekey.bconf
new file mode 100644 (file)
index 0000000..e8d983a
--- /dev/null
@@ -0,0 +1,6 @@
+# Same key value is not allowed
+key {
+       foo = value
+       bar = value2
+}
+key.foo = value
index 1de06de..1411f4c 100755 (executable)
@@ -9,7 +9,7 @@ TEMPCONF=`mktemp temp-XXXX.bconf`
 NG=0
 
 cleanup() {
-  rm -f $INITRD $TEMPCONF
+  rm -f $INITRD $TEMPCONF $OUTFILE
   exit $NG
 }
 
@@ -49,7 +49,7 @@ xpass $BOOTCONF -a $TEMPCONF $INITRD
 new_size=$(stat -c %s $INITRD)
 
 echo "File size check"
-xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9)
+xpass test $new_size -eq $(expr $bconf_size + $initrd_size + 9 + 12)
 
 echo "Apply command repeat test"
 xpass $BOOTCONF -a $TEMPCONF $INITRD
@@ -71,7 +71,6 @@ printf " \0\0\0 \0\0\0" >> $INITRD
 $BOOTCONF -a $TEMPCONF $INITRD > $OUTFILE 2>&1
 xfail grep -i "failed" $OUTFILE
 xfail grep -i "error" $OUTFILE
-rm $OUTFILE
 
 echo "Max node number check"
 
@@ -96,6 +95,19 @@ truncate -s 32764 $TEMPCONF
 echo "\"" >> $TEMPCONF # add 2 bytes + terminal ('\"\n\0')
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 
+echo "Adding same-key values"
+cat > $TEMPCONF << EOF
+key = bar, baz
+key += qux
+EOF
+echo > $INITRD
+
+xpass $BOOTCONF -a $TEMPCONF $INITRD
+$BOOTCONF $INITRD > $OUTFILE
+xpass grep -q "bar" $OUTFILE
+xpass grep -q "baz" $OUTFILE
+xpass grep -q "qux" $OUTFILE
+
 echo "=== expected failure cases ==="
 for i in samples/bad-* ; do
   xfail $BOOTCONF -a $i $INITRD
index c4dd23c..8ead555 100644 (file)
@@ -239,7 +239,6 @@ buildid.*::
                set buildid.dir to /dev/null. The default is $HOME/.debug
 
 annotate.*::
-       These options work only for TUI.
        These are in control of addresses, jump function, source code
        in lines of assembly code from a specific program.
 
@@ -269,6 +268,8 @@ annotate.*::
                â”‚        mov    (%rdi),%rdx
                â”‚              return n;
 
+               This option works with tui, stdio2 browsers.
+
         annotate.use_offset::
                Basing on a first address of a loaded function, offset can be used.
                Instead of using original addresses of assembly code,
@@ -287,6 +288,8 @@ annotate.*::
 
                             368:│  mov    0x8(%r14),%rdi
 
+               This option works with tui, stdio2 browsers.
+
        annotate.jump_arrows::
                There can be jump instruction among assembly code.
                Depending on a boolean value of jump_arrows,
@@ -306,6 +309,8 @@ annotate.*::
                â”‚1330:   mov    %r15,%r10
                â”‚1333:   cmp    %r15,%r14
 
+               This option works with tui browser.
+
         annotate.show_linenr::
                When showing source code if this option is 'true',
                line numbers are printed as below.
@@ -325,6 +330,8 @@ annotate.*::
                â”‚                     array++;
                â”‚             }
 
+               This option works with tui, stdio2 browsers.
+
         annotate.show_nr_jumps::
                Let's see a part of assembly code.
 
@@ -335,6 +342,8 @@ annotate.*::
 
                â”‚1 1382:   movb   $0x1,-0x270(%rbp)
 
+               This option works with tui, stdio2 browsers.
+
         annotate.show_total_period::
                To compare two records on an instruction base, with this option
                provided, display total number of samples that belong to a line
@@ -348,11 +357,30 @@ annotate.*::
 
                99.93 â”‚      mov    %eax,%eax
 
+               This option works with tui, stdio2, stdio browsers.
+
+       annotate.show_nr_samples::
+               By default perf annotate shows percentage of samples. This option
+               can be used to print absolute number of samples. Ex, when set as
+               false:
+
+               Percent│
+                74.03 â”‚      mov    %fs:0x28,%rax
+
+               When set as true:
+
+               Samples│
+                    6 â”‚      mov    %fs:0x28,%rax
+
+               This option works with tui, stdio2, stdio browsers.
+
        annotate.offset_level::
                Default is '1', meaning just jump targets will have offsets show right beside
                the instruction. When set to '2' 'call' instructions will also have its offsets
                shown, 3 or higher will show offsets for all instructions.
 
+               This option works with tui, stdio2 browsers.
+
 hist.*::
        hist.percentage::
                This option control the way to calculate overhead of filtered entries -
@@ -490,6 +518,12 @@ top.*::
                column by default.
                The default is 'true'.
 
+       top.call-graph::
+               This is identical to 'call-graph.record-mode', except it is
+               applicable only for 'top' subcommand. This option ONLY setup
+               the unwind method. To enable 'perf top' to actually use it,
+               the command line option -g must be specified.
+
 man.*::
        man.viewer::
                This option can assign a tool to view manual pages when 'help'
@@ -517,6 +551,16 @@ record.*::
                But if this option is 'no-cache', it will not update the build-id cache.
                'skip' skips post-processing and does not update the cache.
 
+       record.call-graph::
+               This is identical to 'call-graph.record-mode', except it is
+               applicable only for 'record' subcommand. This option ONLY setup
+               the unwind method. To enable 'perf record' to actually use it,
+               the command line option -g must be specified.
+
+       record.aio::
+               Use 'n' control blocks in asynchronous (Posix AIO) trace writing
+               mode ('n' default: 1, max: 4).
+
 diff.*::
        diff.order::
                This option sets the number of columns to sort the result.
@@ -566,6 +610,11 @@ trace.*::
                "libbeauty", the default, to use the same argument beautifiers used in the
                strace-like sys_enter+sys_exit lines.
 
+ftrace.*::
+       ftrace.tracer::
+               Can be used to select the default tracer. Possible values are
+               'function' and 'function_graph'.
+
 llvm.*::
        llvm.clang-path::
                Path to clang. If omit, search it from $PATH.
@@ -610,6 +659,29 @@ scripts.*::
        The script gets the same options passed as a full perf script,
        in particular -i perfdata file, --cpu, --tid
 
+convert.*::
+
+       convert.queue-size::
+               Limit the size of ordered_events queue, so we could control
+               allocation size of perf data files without proper finished
+               round events.
+
+intel-pt.*::
+
+       intel-pt.cache-divisor::
+
+       intel-pt.mispred-all::
+               If set, Intel PT decoder will set the mispred flag on all
+               branches.
+
+auxtrace.*::
+
+       auxtrace.dumpdir::
+               s390 only. The directory to save the auxiliary trace buffer
+               can be changed using this option. Ex, auxtrace.dumpdir=/tmp.
+               If the directory does not exist or has the wrong file type,
+               the current directory is used.
+
 SEE ALSO
 --------
 linkperf:perf[1]
index 2898cfd..941f814 100644 (file)
@@ -858,21 +858,6 @@ static void cs_etm_recording_free(struct auxtrace_record *itr)
        free(ptr);
 }
 
-static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
-{
-       struct cs_etm_recording *ptr =
-                       container_of(itr, struct cs_etm_recording, itr);
-       struct evsel *evsel;
-
-       evlist__for_each_entry(ptr->evlist, evsel) {
-               if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
-                       return perf_evlist__enable_event_idx(ptr->evlist,
-                                                            evsel, idx);
-       }
-
-       return -EINVAL;
-}
-
 struct auxtrace_record *cs_etm_record_init(int *err)
 {
        struct perf_pmu *cs_etm_pmu;
@@ -892,6 +877,7 @@ struct auxtrace_record *cs_etm_record_init(int *err)
        }
 
        ptr->cs_etm_pmu                 = cs_etm_pmu;
+       ptr->itr.pmu                    = cs_etm_pmu;
        ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
        ptr->itr.recording_options      = cs_etm_recording_options;
        ptr->itr.info_priv_size         = cs_etm_info_priv_size;
@@ -901,7 +887,7 @@ struct auxtrace_record *cs_etm_record_init(int *err)
        ptr->itr.snapshot_finish        = cs_etm_snapshot_finish;
        ptr->itr.reference              = cs_etm_reference;
        ptr->itr.free                   = cs_etm_recording_free;
-       ptr->itr.read_finish            = cs_etm_read_finish;
+       ptr->itr.read_finish            = auxtrace_record__read_finish;
 
        *err = 0;
        return &ptr->itr;
index eba6541..8d6821d 100644 (file)
@@ -158,20 +158,6 @@ static void arm_spe_recording_free(struct auxtrace_record *itr)
        free(sper);
 }
 
-static int arm_spe_read_finish(struct auxtrace_record *itr, int idx)
-{
-       struct arm_spe_recording *sper =
-                       container_of(itr, struct arm_spe_recording, itr);
-       struct evsel *evsel;
-
-       evlist__for_each_entry(sper->evlist, evsel) {
-               if (evsel->core.attr.type == sper->arm_spe_pmu->type)
-                       return perf_evlist__enable_event_idx(sper->evlist,
-                                                            evsel, idx);
-       }
-       return -EINVAL;
-}
-
 struct auxtrace_record *arm_spe_recording_init(int *err,
                                               struct perf_pmu *arm_spe_pmu)
 {
@@ -189,12 +175,13 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
        }
 
        sper->arm_spe_pmu = arm_spe_pmu;
+       sper->itr.pmu = arm_spe_pmu;
        sper->itr.recording_options = arm_spe_recording_options;
        sper->itr.info_priv_size = arm_spe_info_priv_size;
        sper->itr.info_fill = arm_spe_info_fill;
        sper->itr.free = arm_spe_recording_free;
        sper->itr.reference = arm_spe_reference;
-       sper->itr.read_finish = arm_spe_read_finish;
+       sper->itr.read_finish = auxtrace_record__read_finish;
        sper->itr.alignment = 0;
 
        *err = 0;
index 43f736e..35b61bf 100644 (file)
 433    common  fspick                          sys_fspick
 434    common  pidfd_open                      sys_pidfd_open
 435    nospu   clone3                          ppc_clone3
+437    common  openat2                         sys_openat2
+438    common  pidfd_getfd                     sys_pidfd_getfd
index 27d9e21..26cee10 100644 (file)
@@ -413,20 +413,6 @@ out_err:
        return err;
 }
 
-static int intel_bts_read_finish(struct auxtrace_record *itr, int idx)
-{
-       struct intel_bts_recording *btsr =
-                       container_of(itr, struct intel_bts_recording, itr);
-       struct evsel *evsel;
-
-       evlist__for_each_entry(btsr->evlist, evsel) {
-               if (evsel->core.attr.type == btsr->intel_bts_pmu->type)
-                       return perf_evlist__enable_event_idx(btsr->evlist,
-                                                            evsel, idx);
-       }
-       return -EINVAL;
-}
-
 struct auxtrace_record *intel_bts_recording_init(int *err)
 {
        struct perf_pmu *intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
@@ -447,6 +433,7 @@ struct auxtrace_record *intel_bts_recording_init(int *err)
        }
 
        btsr->intel_bts_pmu = intel_bts_pmu;
+       btsr->itr.pmu = intel_bts_pmu;
        btsr->itr.recording_options = intel_bts_recording_options;
        btsr->itr.info_priv_size = intel_bts_info_priv_size;
        btsr->itr.info_fill = intel_bts_info_fill;
@@ -456,7 +443,7 @@ struct auxtrace_record *intel_bts_recording_init(int *err)
        btsr->itr.find_snapshot = intel_bts_find_snapshot;
        btsr->itr.parse_snapshot_options = intel_bts_parse_snapshot_options;
        btsr->itr.reference = intel_bts_reference;
-       btsr->itr.read_finish = intel_bts_read_finish;
+       btsr->itr.read_finish = auxtrace_record__read_finish;
        btsr->itr.alignment = sizeof(struct branch);
        return &btsr->itr;
 }
index 20df442..7eea4fd 100644 (file)
@@ -1166,20 +1166,6 @@ static u64 intel_pt_reference(struct auxtrace_record *itr __maybe_unused)
        return rdtsc();
 }
 
-static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
-{
-       struct intel_pt_recording *ptr =
-                       container_of(itr, struct intel_pt_recording, itr);
-       struct evsel *evsel;
-
-       evlist__for_each_entry(ptr->evlist, evsel) {
-               if (evsel->core.attr.type == ptr->intel_pt_pmu->type)
-                       return perf_evlist__enable_event_idx(ptr->evlist, evsel,
-                                                            idx);
-       }
-       return -EINVAL;
-}
-
 struct auxtrace_record *intel_pt_recording_init(int *err)
 {
        struct perf_pmu *intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME);
@@ -1200,6 +1186,7 @@ struct auxtrace_record *intel_pt_recording_init(int *err)
        }
 
        ptr->intel_pt_pmu = intel_pt_pmu;
+       ptr->itr.pmu = intel_pt_pmu;
        ptr->itr.recording_options = intel_pt_recording_options;
        ptr->itr.info_priv_size = intel_pt_info_priv_size;
        ptr->itr.info_fill = intel_pt_info_fill;
@@ -1209,7 +1196,7 @@ struct auxtrace_record *intel_pt_recording_init(int *err)
        ptr->itr.find_snapshot = intel_pt_find_snapshot;
        ptr->itr.parse_snapshot_options = intel_pt_parse_snapshot_options;
        ptr->itr.reference = intel_pt_reference;
-       ptr->itr.read_finish = intel_pt_read_finish;
+       ptr->itr.read_finish = auxtrace_record__read_finish;
        /*
         * Decoding starts at a PSB packet. Minimum PSB period is 2K so 4K
         * should give at least 1 PSB per sample.
index ff61795..6c0a041 100644 (file)
@@ -566,6 +566,8 @@ int cmd_annotate(int argc, const char **argv)
        if (ret < 0)
                return ret;
 
+       annotation_config__init(&annotate.opts);
+
        argc = parse_options(argc, argv, options, annotate_usage, 0);
        if (argc) {
                /*
@@ -605,8 +607,6 @@ int cmd_annotate(int argc, const char **argv)
        if (ret < 0)
                goto out_delete;
 
-       annotation_config__init();
-
        symbol_conf.try_vmlinux_path = true;
 
        ret = symbol__init(&annotate.session->header.env);
index 26bc592..70548df 100644 (file)
@@ -449,7 +449,8 @@ static int perf_del_probe_events(struct strfilter *filter)
                ret = probe_file__del_strlist(kfd, klist);
                if (ret < 0)
                        goto error;
-       }
+       } else if (ret == -ENOMEM)
+               goto error;
 
        ret2 = probe_file__get_events(ufd, filter, ulist);
        if (ret2 == 0) {
@@ -459,7 +460,8 @@ static int perf_del_probe_events(struct strfilter *filter)
                ret2 = probe_file__del_strlist(ufd, ulist);
                if (ret2 < 0)
                        goto error;
-       }
+       } else if (ret2 == -ENOMEM)
+               goto error;
 
        if (ret == -ENOENT && ret2 == -ENOENT)
                pr_warning("\"%s\" does not hit any event.\n", str);
index 9483b3f..72a12b6 100644 (file)
@@ -1507,7 +1507,7 @@ repeat:
                        symbol_conf.priv_size += sizeof(u32);
                        symbol_conf.sort_by_name = true;
                }
-               annotation_config__init();
+               annotation_config__init(&report.annotation_opts);
        }
 
        if (symbol__init(&session->header.env) < 0)
index 8affcab..f6dd1a6 100644 (file)
@@ -143,7 +143,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
                return err;
        }
 
-       err = symbol__annotate(&he->ms, evsel, 0, &top->annotation_opts, NULL);
+       err = symbol__annotate(&he->ms, evsel, &top->annotation_opts, NULL);
        if (err == 0) {
                top->sym_filter_entry = he;
        } else {
@@ -1683,7 +1683,7 @@ int cmd_top(int argc, const char **argv)
        if (status < 0)
                goto out_delete_evlist;
 
-       annotation_config__init();
+       annotation_config__init(&top.annotation_opts);
 
        symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
        status = symbol__init(NULL);
index 607189a..6e61c4b 100644 (file)
@@ -3,7 +3,7 @@
 #ifndef _PERF_BPF_PID_FILTER_
 #define _PERF_BPF_PID_FILTER_
 
-#include <bpf/bpf.h>
+#include <bpf.h>
 
 #define pid_filter(name) pid_map(name, bool)
 
index 7ca6fa5..316af5b 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
-#include <bpf/bpf.h>
+#include <bpf.h>
 
 struct bpf_map SEC("maps") __bpf_stdout__ = {
        .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
index d1a35b6..ca7877f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: LGPL-2.1
 
-#include <bpf/bpf.h>
+#include <bpf.h>
 
 static int (*bpf_get_current_pid_tgid)(void) = (void *)BPF_FUNC_get_current_pid_tgid;
 
index 7cb99b4..c2cc42d 100644 (file)
@@ -14,7 +14,7 @@ add_probe_vfs_getname() {
        if [ $had_vfs_getname -eq 1 ] ; then
                line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/')
                perf probe -q       "vfs_getname=getname_flags:${line} pathname=result->name:string" || \
-               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:string"
+               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:ustring"
        fi
 }
 
index badbddb..9023267 100644 (file)
@@ -754,10 +754,9 @@ static int annotate_browser__run(struct annotate_browser *browser,
                "?             Search string backwards\n");
                        continue;
                case 'r':
-                       {
-                               script_browse(NULL, NULL);
-                               continue;
-                       }
+                       script_browse(NULL, NULL);
+                       annotate_browser__show(&browser->b, title, help);
+                       continue;
                case 'k':
                        notes->options->show_linenr = !notes->options->show_linenr;
                        break;
@@ -834,13 +833,13 @@ show_sup_ins:
                        map_symbol__annotation_dump(ms, evsel, browser->opts);
                        continue;
                case 't':
-                       if (notes->options->show_total_period) {
-                               notes->options->show_total_period = false;
-                               notes->options->show_nr_samples = true;
-                       } else if (notes->options->show_nr_samples)
-                               notes->options->show_nr_samples = false;
+                       if (symbol_conf.show_total_period) {
+                               symbol_conf.show_total_period = false;
+                               symbol_conf.show_nr_samples = true;
+                       } else if (symbol_conf.show_nr_samples)
+                               symbol_conf.show_nr_samples = false;
                        else
-                               notes->options->show_total_period = true;
+                               symbol_conf.show_total_period = true;
                        annotation__update_column_widths(notes);
                        continue;
                case 'c':
index 22cc240..35f9641 100644 (file)
@@ -174,7 +174,7 @@ static int symbol__gtk_annotate(struct map_symbol *ms, struct evsel *evsel,
        if (ms->map->dso->annotate_warned)
                return -1;
 
-       err = symbol__annotate(ms, evsel, 0, &annotation__default_options, NULL);
+       err = symbol__annotate(ms, evsel, &annotation__default_options, NULL);
        if (err) {
                char msg[BUFSIZ];
                symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
index ca73fb7..0ea95be 100644 (file)
@@ -1143,93 +1143,70 @@ out:
 }
 
 struct annotate_args {
-       size_t                   privsize;
-       struct arch             *arch;
-       struct map_symbol        ms;
-       struct evsel    *evsel;
+       struct arch               *arch;
+       struct map_symbol         ms;
+       struct evsel              *evsel;
        struct annotation_options *options;
-       s64                      offset;
-       char                    *line;
-       int                      line_nr;
+       s64                       offset;
+       char                      *line;
+       int                       line_nr;
 };
 
-static void annotation_line__delete(struct annotation_line *al)
+static void annotation_line__init(struct annotation_line *al,
+                                 struct annotate_args *args,
+                                 int nr)
 {
-       void *ptr = (void *) al - al->privsize;
+       al->offset = args->offset;
+       al->line = strdup(args->line);
+       al->line_nr = args->line_nr;
+       al->data_nr = nr;
+}
 
+static void annotation_line__exit(struct annotation_line *al)
+{
        free_srcline(al->path);
        zfree(&al->line);
-       free(ptr);
 }
 
-/*
- * Allocating the annotation line data with following
- * structure:
- *
- *    --------------------------------------
- *    private space | struct annotation_line
- *    --------------------------------------
- *
- * Size of the private space is stored in 'struct annotation_line'.
- *
- */
-static struct annotation_line *
-annotation_line__new(struct annotate_args *args, size_t privsize)
+static size_t disasm_line_size(int nr)
 {
        struct annotation_line *al;
-       struct evsel *evsel = args->evsel;
-       size_t size = privsize + sizeof(*al);
-       int nr = 1;
-
-       if (perf_evsel__is_group_event(evsel))
-               nr = evsel->core.nr_members;
 
-       size += sizeof(al->data[0]) * nr;
-
-       al = zalloc(size);
-       if (al) {
-               al = (void *) al + privsize;
-               al->privsize   = privsize;
-               al->offset     = args->offset;
-               al->line       = strdup(args->line);
-               al->line_nr    = args->line_nr;
-               al->data_nr    = nr;
-       }
-
-       return al;
+       return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));
 }
 
 /*
  * Allocating the disasm annotation line data with
  * following structure:
  *
- *    ------------------------------------------------------------
- *    privsize space | struct disasm_line | struct annotation_line
- *    ------------------------------------------------------------
+ *    -------------------------------------------
+ *    struct disasm_line | struct annotation_line
+ *    -------------------------------------------
  *
  * We have 'struct annotation_line' member as last member
  * of 'struct disasm_line' to have an easy access.
- *
  */
 static struct disasm_line *disasm_line__new(struct annotate_args *args)
 {
        struct disasm_line *dl = NULL;
-       struct annotation_line *al;
-       size_t privsize = args->privsize + offsetof(struct disasm_line, al);
+       int nr = 1;
 
-       al = annotation_line__new(args, privsize);
-       if (al != NULL) {
-               dl = disasm_line(al);
+       if (perf_evsel__is_group_event(args->evsel))
+               nr = args->evsel->core.nr_members;
 
-               if (dl->al.line == NULL)
-                       goto out_delete;
+       dl = zalloc(disasm_line_size(nr));
+       if (!dl)
+               return NULL;
 
-               if (args->offset != -1) {
-                       if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
-                               goto out_free_line;
+       annotation_line__init(&dl->al, args, nr);
+       if (dl->al.line == NULL)
+               goto out_delete;
 
-                       disasm_line__init_ins(dl, args->arch, &args->ms);
-               }
+       if (args->offset != -1) {
+               if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
+                       goto out_free_line;
+
+               disasm_line__init_ins(dl, args->arch, &args->ms);
        }
 
        return dl;
@@ -1248,7 +1225,8 @@ void disasm_line__free(struct disasm_line *dl)
        else
                ins__delete(&dl->ops);
        zfree(&dl->ins.name);
-       annotation_line__delete(&dl->al);
+       annotation_line__exit(&dl->al);
+       free(dl);
 }
 
 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)
@@ -2149,13 +2127,12 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
        annotation__calc_percent(notes, evsel, symbol__size(sym));
 }
 
-int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, size_t privsize,
+int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
                     struct annotation_options *options, struct arch **parch)
 {
        struct symbol *sym = ms->sym;
        struct annotation *notes = symbol__annotation(sym);
        struct annotate_args args = {
-               .privsize       = privsize,
                .evsel          = evsel,
                .options        = options,
        };
@@ -2644,6 +2621,8 @@ void annotation__set_offsets(struct annotation *notes, s64 size)
        struct annotation_line *al;
 
        notes->max_line_len = 0;
+       notes->nr_entries = 0;
+       notes->nr_asm_entries = 0;
 
        list_for_each_entry(al, &notes->src->source, node) {
                size_t line_len = strlen(al->line);
@@ -2790,7 +2769,7 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
        struct symbol *sym = ms->sym;
        struct rb_root source_line = RB_ROOT;
 
-       if (symbol__annotate(ms, evsel, 0, opts, NULL) < 0)
+       if (symbol__annotate(ms, evsel, opts, NULL) < 0)
                return -1;
 
        symbol__calc_percent(sym, evsel);
@@ -2915,9 +2894,9 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
                        percent = annotation_data__percent(&al->data[i], percent_type);
 
                        obj__set_percent_color(obj, percent, current_entry);
-                       if (notes->options->show_total_period) {
+                       if (symbol_conf.show_total_period) {
                                obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
-                       } else if (notes->options->show_nr_samples) {
+                       } else if (symbol_conf.show_nr_samples) {
                                obj__printf(obj, "%6" PRIu64 " ",
                                                   al->data[i].he.nr_samples);
                        } else {
@@ -2931,8 +2910,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
                        obj__printf(obj, "%-*s", pcnt_width, " ");
                else {
                        obj__printf(obj, "%-*s", pcnt_width,
-                                          notes->options->show_total_period ? "Period" :
-                                          notes->options->show_nr_samples ? "Samples" : "Percent");
+                                          symbol_conf.show_total_period ? "Period" :
+                                          symbol_conf.show_nr_samples ? "Samples" : "Percent");
                }
        }
 
@@ -3070,7 +3049,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
        if (perf_evsel__is_group_event(evsel))
                nr_pcnt = evsel->core.nr_members;
 
-       err = symbol__annotate(ms, evsel, 0, options, parch);
+       err = symbol__annotate(ms, evsel, options, parch);
        if (err)
                goto out_free_offsets;
 
@@ -3094,69 +3073,46 @@ out_free_offsets:
        return err;
 }
 
-#define ANNOTATION__CFG(n) \
-       { .name = #n, .value = &annotation__default_options.n, }
-
-/*
- * Keep the entries sorted, they are bsearch'ed
- */
-static struct annotation_config {
-       const char *name;
-       void *value;
-} annotation__configs[] = {
-       ANNOTATION__CFG(hide_src_code),
-       ANNOTATION__CFG(jump_arrows),
-       ANNOTATION__CFG(offset_level),
-       ANNOTATION__CFG(show_linenr),
-       ANNOTATION__CFG(show_nr_jumps),
-       ANNOTATION__CFG(show_nr_samples),
-       ANNOTATION__CFG(show_total_period),
-       ANNOTATION__CFG(use_offset),
-};
-
-#undef ANNOTATION__CFG
-
-static int annotation_config__cmp(const void *name, const void *cfgp)
-{
-       const struct annotation_config *cfg = cfgp;
-
-       return strcmp(name, cfg->name);
-}
-
-static int annotation__config(const char *var, const char *value,
-                           void *data __maybe_unused)
+static int annotation__config(const char *var, const char *value, void *data)
 {
-       struct annotation_config *cfg;
-       const char *name;
+       struct annotation_options *opt = data;
 
        if (!strstarts(var, "annotate."))
                return 0;
 
-       name = var + 9;
-       cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
-                     sizeof(struct annotation_config), annotation_config__cmp);
-
-       if (cfg == NULL)
-               pr_debug("%s variable unknown, ignoring...", var);
-       else if (strcmp(var, "annotate.offset_level") == 0) {
-               perf_config_int(cfg->value, name, value);
-
-               if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
-                       *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
-               else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
-                       *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
+       if (!strcmp(var, "annotate.offset_level")) {
+               perf_config_u8(&opt->offset_level, "offset_level", value);
+
+               if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
+                       opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL;
+               else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
+                       opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
+       } else if (!strcmp(var, "annotate.hide_src_code")) {
+               opt->hide_src_code = perf_config_bool("hide_src_code", value);
+       } else if (!strcmp(var, "annotate.jump_arrows")) {
+               opt->jump_arrows = perf_config_bool("jump_arrows", value);
+       } else if (!strcmp(var, "annotate.show_linenr")) {
+               opt->show_linenr = perf_config_bool("show_linenr", value);
+       } else if (!strcmp(var, "annotate.show_nr_jumps")) {
+               opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value);
+       } else if (!strcmp(var, "annotate.show_nr_samples")) {
+               symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples",
+                                                               value);
+       } else if (!strcmp(var, "annotate.show_total_period")) {
+               symbol_conf.show_total_period = perf_config_bool("show_total_period",
+                                                               value);
+       } else if (!strcmp(var, "annotate.use_offset")) {
+               opt->use_offset = perf_config_bool("use_offset", value);
        } else {
-               *(bool *)cfg->value = perf_config_bool(name, value);
+               pr_debug("%s variable unknown, ignoring...", var);
        }
+
        return 0;
 }
 
-void annotation_config__init(void)
+void annotation_config__init(struct annotation_options *opt)
 {
-       perf_config(annotation__config, NULL);
-
-       annotation__default_options.show_total_period = symbol_conf.show_total_period;
-       annotation__default_options.show_nr_samples   = symbol_conf.show_nr_samples;
+       perf_config(annotation__config, opt);
 }
 
 static unsigned int parse_percent_type(char *str1, char *str2)
index 455403e..0012586 100644 (file)
@@ -83,8 +83,6 @@ struct annotation_options {
             full_path,
             show_linenr,
             show_nr_jumps,
-            show_nr_samples,
-            show_total_period,
             show_minmax_cycle,
             show_asm_raw,
             annotate_src;
@@ -141,7 +139,6 @@ struct annotation_line {
        u64                      cycles;
        u64                      cycles_max;
        u64                      cycles_min;
-       size_t                   privsize;
        char                    *path;
        u32                      idx;
        int                      idx_asm;
@@ -309,7 +306,7 @@ static inline int annotation__cycles_width(struct annotation *notes)
 
 static inline int annotation__pcnt_width(struct annotation *notes)
 {
-       return (notes->options->show_total_period ? 12 : 7) * notes->nr_events;
+       return (symbol_conf.show_total_period ? 12 : 7) * notes->nr_events;
 }
 
 static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
@@ -352,7 +349,7 @@ struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists);
 void symbol__annotate_zero_histograms(struct symbol *sym);
 
 int symbol__annotate(struct map_symbol *ms,
-                    struct evsel *evsel, size_t privsize,
+                    struct evsel *evsel,
                     struct annotation_options *options,
                     struct arch **parch);
 int symbol__annotate2(struct map_symbol *ms,
@@ -413,7 +410,7 @@ static inline int symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
 }
 #endif
 
-void annotation_config__init(void);
+void annotation_config__init(struct annotation_options *opt);
 
 int annotate_parse_percent_type(const struct option *opt, const char *_str,
                                int unset);
index eb087e7..3571ce7 100644 (file)
@@ -629,8 +629,10 @@ int auxtrace_record__options(struct auxtrace_record *itr,
                             struct evlist *evlist,
                             struct record_opts *opts)
 {
-       if (itr)
+       if (itr) {
+               itr->evlist = evlist;
                return itr->recording_options(itr, evlist, opts);
+       }
        return 0;
 }
 
@@ -664,6 +666,24 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
        return -EINVAL;
 }
 
+int auxtrace_record__read_finish(struct auxtrace_record *itr, int idx)
+{
+       struct evsel *evsel;
+
+       if (!itr->evlist || !itr->pmu)
+               return -EINVAL;
+
+       evlist__for_each_entry(itr->evlist, evsel) {
+               if (evsel->core.attr.type == itr->pmu->type) {
+                       if (evsel->disabled)
+                               return 0;
+                       return perf_evlist__enable_event_idx(itr->evlist, evsel,
+                                                            idx);
+               }
+       }
+       return -EINVAL;
+}
+
 /*
  * Event record size is 16-bit which results in a maximum size of about 64KiB.
  * Allow about 4KiB for the rest of the sample record, to give a maximum
index 749d72c..e58ef16 100644 (file)
@@ -29,6 +29,7 @@ struct record_opts;
 struct perf_record_auxtrace_error;
 struct perf_record_auxtrace_info;
 struct events_stats;
+struct perf_pmu;
 
 enum auxtrace_error_type {
        PERF_AUXTRACE_ERROR_ITRACE  = 1,
@@ -322,6 +323,8 @@ struct auxtrace_mmap_params {
  * @read_finish: called after reading from an auxtrace mmap
  * @alignment: alignment (if any) for AUX area data
  * @default_aux_sample_size: default sample size for --aux sample option
+ * @pmu: associated pmu
+ * @evlist: selected events list
  */
 struct auxtrace_record {
        int (*recording_options)(struct auxtrace_record *itr,
@@ -346,6 +349,8 @@ struct auxtrace_record {
        int (*read_finish)(struct auxtrace_record *itr, int idx);
        unsigned int alignment;
        unsigned int default_aux_sample_size;
+       struct perf_pmu *pmu;
+       struct evlist *evlist;
 };
 
 /**
@@ -537,6 +542,7 @@ int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
                                   struct auxtrace_mmap *mm,
                                   unsigned char *data, u64 *head, u64 *old);
 u64 auxtrace_record__reference(struct auxtrace_record *itr);
+int auxtrace_record__read_finish(struct auxtrace_record *itr, int idx);
 
 int auxtrace_index__auxtrace_event(struct list_head *head, union perf_event *event,
                                   off_t file_offset);
index 0bc9c4d..ef38eba 100644 (file)
@@ -374,6 +374,18 @@ int perf_config_int(int *dest, const char *name, const char *value)
        return 0;
 }
 
+int perf_config_u8(u8 *dest, const char *name, const char *value)
+{
+       long ret = 0;
+
+       if (!perf_parse_long(value, &ret)) {
+               bad_config(name);
+               return -1;
+       }
+       *dest = ret;
+       return 0;
+}
+
 static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
 {
        int ret;
index bd0a589..c10b66d 100644 (file)
@@ -29,6 +29,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
 int perf_default_config(const char *, const char *, void *);
 int perf_config(config_fn_t fn, void *);
 int perf_config_int(int *dest, const char *, const char *);
+int perf_config_u8(u8 *dest, const char *name, const char *value);
 int perf_config_u64(u64 *dest, const char *, const char *);
 int perf_config_bool(const char *, const char *);
 int config_error_nonbool(const char *);
index 5003ba4..0f5fda1 100644 (file)
@@ -301,10 +301,15 @@ int probe_file__get_events(int fd, struct strfilter *filter,
                p = strchr(ent->s, ':');
                if ((p && strfilter__compare(filter, p + 1)) ||
                    strfilter__compare(filter, ent->s)) {
-                       strlist__add(plist, ent->s);
+                       ret = strlist__add(plist, ent->s);
+                       if (ret == -ENOMEM) {
+                               pr_err("strlist__add failed with -ENOMEM\n");
+                               goto out;
+                       }
                        ret = 0;
                }
        }
+out:
        strlist__delete(namelist);
 
        return ret;
@@ -511,7 +516,11 @@ static int probe_cache__load(struct probe_cache *pcache)
                                ret = -EINVAL;
                                goto out;
                        }
-                       strlist__add(entry->tevlist, buf);
+                       ret = strlist__add(entry->tevlist, buf);
+                       if (ret == -ENOMEM) {
+                               pr_err("strlist__add failed with -ENOMEM\n");
+                               goto out;
+                       }
                }
        }
 out:
@@ -672,7 +681,12 @@ int probe_cache__add_entry(struct probe_cache *pcache,
                command = synthesize_probe_trace_command(&tevs[i]);
                if (!command)
                        goto out_err;
-               strlist__add(entry->tevlist, command);
+               ret = strlist__add(entry->tevlist, command);
+               if (ret == -ENOMEM) {
+                       pr_err("strlist__add failed with -ENOMEM\n");
+                       goto out_err;
+               }
+
                free(command);
        }
        list_add_tail(&entry->node, &pcache->entries);
@@ -853,9 +867,15 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
                        break;
                }
 
-               strlist__add(entry->tevlist, buf);
+               ret = strlist__add(entry->tevlist, buf);
+
                free(buf);
                entry = NULL;
+
+               if (ret == -ENOMEM) {
+                       pr_err("strlist__add failed with -ENOMEM\n");
+                       break;
+               }
        }
        if (entry) {
                list_del_init(&entry->node);
index 220d04f..7570e36 100755 (executable)
@@ -30,7 +30,7 @@ my %default = (
     "EMAIL_WHEN_STARTED"       => 0,
     "NUM_TESTS"                        => 1,
     "TEST_TYPE"                        => "build",
-    "BUILD_TYPE"               => "randconfig",
+    "BUILD_TYPE"               => "oldconfig",
     "MAKE_CMD"                 => "make",
     "CLOSE_CONSOLE_SIGNAL"     => "INT",
     "TIMEOUT"                  => 120,
@@ -1030,7 +1030,7 @@ sub __read_config {
            }
 
            if (!$skip && $rest !~ /^\s*$/) {
-               die "$name: $.: Gargbage found after $type\n$_";
+               die "$name: $.: Garbage found after $type\n$_";
            }
 
            if ($skip && $type eq "TEST_START") {
@@ -1063,7 +1063,7 @@ sub __read_config {
            }
 
            if ($rest !~ /^\s*$/) {
-               die "$name: $.: Gargbage found after DEFAULTS\n$_";
+               die "$name: $.: Garbage found after DEFAULTS\n$_";
            }
 
        } elsif (/^\s*INCLUDE\s+(\S+)/) {
@@ -1154,7 +1154,7 @@ sub __read_config {
            # on of these sections that have SKIP defined.
            # The save variable can be
            # defined multiple times and the new one simply overrides
-           # the prevous one.
+           # the previous one.
            set_variable($lvalue, $rvalue);
 
        } else {
@@ -1234,7 +1234,7 @@ sub read_config {
        foreach my $option (keys %not_used) {
            print "$option\n";
        }
-       print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
+       print "Set IGNORE_UNUSED = 1 to have ktest ignore unused variables\n";
        if (!read_yn "Do you want to continue?") {
            exit -1;
        }
@@ -1345,7 +1345,7 @@ sub eval_option {
        # Check for recursive evaluations.
        # 100 deep should be more than enough.
        if ($r++ > 100) {
-           die "Over 100 evaluations accurred with $option\n" .
+           die "Over 100 evaluations occurred with $option\n" .
                "Check for recursive variables\n";
        }
        $prev = $option;
@@ -1383,7 +1383,7 @@ sub reboot {
 
     } else {
        # Make sure everything has been written to disk
-       run_ssh("sync");
+       run_ssh("sync", 10);
 
        if (defined($time)) {
            start_monitor;
@@ -1461,7 +1461,7 @@ sub get_test_name() {
 
 sub dodie {
 
-    # avoid recusion
+    # avoid recursion
     return if ($in_die);
     $in_die = 1;
 
index c3bc933..27666b8 100644 (file)
@@ -10,7 +10,7 @@
 #
 
 # Options set in the beginning of the file are considered to be
-# default options. These options can be overriden by test specific
+# default options. These options can be overridden by test specific
 # options, with the following exceptions:
 #
 #  LOG_FILE
 #
 # This config file can also contain "config variables".
 # These are assigned with ":=" instead of the ktest option
-# assigment "=".
+# assignment "=".
 #
 # The difference between ktest options and config variables
 # is that config variables can be used multiple times,
 #### Using options in other options ####
 #
 # Options that are defined in the config file may also be used
-# by other options. All options are evaulated at time of
+# by other options. All options are evaluated at time of
 # use (except that config variables are evaluated at config
 # processing time).
 #
 #TEST = ssh user@machine /root/run_test
 
 # The build type is any make config type or special command
-#  (default randconfig)
+#  (default oldconfig)
 #   nobuild - skip the clean and build step
 #   useconfig:/path/to/config - use the given config and run
 #              oldconfig on it.
 
 # Line to define a successful boot up in console output.
 # This is what the line contains, not the entire line. If you need
-# the entire line to match, then use regural expression syntax like:
+# the entire line to match, then use regular expression syntax like:
 #  (do not add any quotes around it)
 #
 #  SUCCESS_LINE = ^MyBox Login:$
 # (ignored if POWEROFF_ON_SUCCESS is set)
 #REBOOT_ON_SUCCESS = 1
 
-# In case there are isses with rebooting, you can specify this
+# In case there are issues with rebooting, you can specify this
 # to always powercycle after this amount of time after calling
 # reboot.
 # Note, POWERCYCLE_AFTER_REBOOT = 0 does NOT disable it. It just
 # (default undefined)
 #POWERCYCLE_AFTER_REBOOT = 5
 
-# In case there's isses with halting, you can specify this
+# In case there's issues with halting, you can specify this
 # to always poweroff after this amount of time after calling
 # halt.
 # Note, POWEROFF_AFTER_HALT = 0 does NOT disable it. It just
 #
 #  PATCHCHECK_START is required and is the first patch to
 #   test (the SHA1 of the commit). You may also specify anything
-#   that git checkout allows (branch name, tage, HEAD~3).
+#   that git checkout allows (branch name, tag, HEAD~3).
 #
 #  PATCHCHECK_END is the last patch to check (default HEAD)
 #
 #     IGNORE_WARNINGS is set for the given commit's sha1
 #
 #   IGNORE_WARNINGS can be used to disable the failure of patchcheck
-#     on a particuler commit (SHA1). You can add more than one commit
+#     on a particular commit (SHA1). You can add more than one commit
 #     by adding a list of SHA1s that are space delimited.
 #
 #   If BUILD_NOCLEAN is set, then make mrproper will not be run on
 #   whatever reason. (Can't reboot, want to inspect each iteration)
 #   Doing a BISECT_MANUAL will have the test wait for you to
 #   tell it if the test passed or failed after each iteration.
-#   This is basicall the same as running git bisect yourself
+#   This is basically the same as running git bisect yourself
 #   but ktest will rebuild and install the kernel for you.
 #
 # BISECT_CHECK = 1 (optional, default 0)
 #
 # CONFIG_BISECT_EXEC (optional)
 #  The config bisect is a separate program that comes with ktest.pl.
-#  By befault, it will look for:
+#  By default, it will look for:
 #    `pwd`/config-bisect.pl # the location ktest.pl was executed from.
 #  If it does not find it there, it will look for:
 #    `dirname <ktest.pl>`/config-bisect.pl # The directory that holds ktest.pl
index e59eb9e..180ad1e 100755 (executable)
@@ -24,6 +24,8 @@ KunitResult = namedtuple('KunitResult', ['status','result'])
 
 KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
 
+KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0]
+
 class KunitStatus(Enum):
        SUCCESS = auto()
        CONFIG_FAILURE = auto()
@@ -35,6 +37,13 @@ def create_default_kunitconfig():
                shutil.copyfile('arch/um/configs/kunit_defconfig',
                                kunit_kernel.kunitconfig_path)
 
+def get_kernel_root_path():
+       parts = sys.argv[0] if not __file__ else __file__
+       parts = os.path.realpath(parts).split('tools/testing/kunit')
+       if len(parts) != 2:
+               sys.exit(1)
+       return parts[0]
+
 def run_tests(linux: kunit_kernel.LinuxSourceTree,
              request: KunitRequest) -> KunitResult:
        config_start = time.time()
@@ -114,6 +123,9 @@ def main(argv, linux=None):
        cli_args = parser.parse_args(argv)
 
        if cli_args.subcommand == 'run':
+               if get_kernel_root_path():
+                       os.chdir(get_kernel_root_path())
+
                if cli_args.build_dir:
                        if not os.path.exists(cli_args.build_dir):
                                os.mkdir(cli_args.build_dir)
index cc5d844..d99ae75 100644 (file)
@@ -93,6 +93,20 @@ class LinuxSourceTree(object):
                        return False
                return True
 
+       def validate_config(self, build_dir):
+               kconfig_path = get_kconfig_path(build_dir)
+               validated_kconfig = kunit_config.Kconfig()
+               validated_kconfig.read_from_file(kconfig_path)
+               if not self._kconfig.is_subset_of(validated_kconfig):
+                       invalid = self._kconfig.entries() - validated_kconfig.entries()
+                       message = 'Provided Kconfig is not contained in validated .config. Following fields found in kunitconfig, ' \
+                                         'but not in .config: %s' % (
+                                       ', '.join([str(e) for e in invalid])
+                       )
+                       logging.error(message)
+                       return False
+               return True
+
        def build_config(self, build_dir):
                kconfig_path = get_kconfig_path(build_dir)
                if build_dir and not os.path.exists(build_dir):
@@ -103,12 +117,7 @@ class LinuxSourceTree(object):
                except ConfigError as e:
                        logging.error(e)
                        return False
-               validated_kconfig = kunit_config.Kconfig()
-               validated_kconfig.read_from_file(kconfig_path)
-               if not self._kconfig.is_subset_of(validated_kconfig):
-                       logging.error('Provided Kconfig is not contained in validated .config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def build_reconfig(self, build_dir):
                """Creates a new .config if it is not a subset of the .kunitconfig."""
@@ -133,12 +142,7 @@ class LinuxSourceTree(object):
                except (ConfigError, BuildError) as e:
                        logging.error(e)
                        return False
-               used_kconfig = kunit_config.Kconfig()
-               used_kconfig.read_from_file(get_kconfig_path(build_dir))
-               if not self._kconfig.is_subset_of(used_kconfig):
-                       logging.error('Provided Kconfig is not contained in final config!')
-                       return False
-               return True
+               return self.validate_config(build_dir)
 
        def run_kernel(self, args=[], timeout=None, build_dir=''):
                args.extend(['mem=256M'])
index cd1f5b3..d6e106f 100644 (file)
@@ -2,7 +2,7 @@
 all:
 
 TEST_PROGS := ftracetest
-TEST_FILES := test.d
+TEST_FILES := test.d settings
 EXTRA_CLEAN := $(OUTPUT)/logs/*
 
 include ../lib.mk
index 3876d8d..1acc9e1 100644 (file)
@@ -8,4 +8,6 @@ TEST_PROGS := \
        test-state.sh \
        test-ftrace.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
diff --git a/tools/testing/selftests/lkdtm/.gitignore b/tools/testing/selftests/lkdtm/.gitignore
new file mode 100644 (file)
index 0000000..f262126
--- /dev/null
@@ -0,0 +1,2 @@
+*.sh
+!run.sh
index 60273f1..b761670 100755 (executable)
@@ -1041,6 +1041,27 @@ ipv6_addr_metric_test()
        fi
        log_test $rc 0 "Prefix route with metric on link up"
 
+       # verify peer metric added correctly
+       set -e
+       run_cmd "$IP -6 addr flush dev dummy2"
+       run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
+       set +e
+
+       check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
+       log_test $? 0 "Set metric with peer route on local side"
+       log_test $? 0 "User specified metric on local address"
+       check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
+       log_test $? 0 "Set metric with peer route on peer side"
+
+       set -e
+       run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
+       set +e
+
+       check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
+       log_test $? 0 "Modify metric and peer address on local side"
+       check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
+       log_test $? 0 "Modify metric and peer address on peer side"
+
        $IP li del dummy1
        $IP li del dummy2
        cleanup
@@ -1457,13 +1478,20 @@ ipv4_addr_metric_test()
 
        run_cmd "$IP addr flush dev dummy2"
        run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
-       run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 261"
        rc=$?
        if [ $rc -eq 0 ]; then
-               check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
+               check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
+               rc=$?
+       fi
+       log_test $rc 0 "Set metric of address with peer route"
+
+       run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
+       rc=$?
+       if [ $rc -eq 0 ]; then
+               check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
                rc=$?
        fi
-       log_test $rc 0 "Modify metric of address with peer route"
+       log_test $rc 0 "Modify metric and peer address for peer route"
 
        $IP li del dummy1
        $IP li del dummy2
index 93de520..ba450e6 100644 (file)
@@ -8,6 +8,8 @@ TEST_PROGS := mptcp_connect.sh
 
 TEST_GEN_FILES = mptcp_connect
 
+TEST_FILES := settings
+
 EXTRA_CLEAN := *.pcap
 
 include ../../lib.mk
index aca21dd..5a4938d 100755 (executable)
 KSELFTEST_SKIP=4
 
 # Available test groups:
+# - reported_issues: check for issues that were reported in the past
 # - correctness: check that packets match given entries, and only those
 # - concurrency: attempt races between insertion, deletion and lookup
 # - timeout: check that packets match entries until they expire
 # - performance: estimate matching rate, compare with rbtree and hash baselines
-TESTS="correctness concurrency timeout"
+TESTS="reported_issues correctness concurrency timeout"
 [ "${quicktest}" != "1" ] && TESTS="${TESTS} performance"
 
 # Set types, defined by TYPE_ variables below
@@ -25,6 +26,9 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
        net_port_net net_mac net_mac_icmp net6_mac_icmp net6_port_net6_port
        net_port_mac_proto_net"
 
+# Reported bugs, also described by TYPE_ variables below
+BUGS="flush_remove_add"
+
 # List of possible paths to pktgen script from kernel tree for performance tests
 PKTGEN_SCRIPT_PATHS="
        ../../../samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh
@@ -327,6 +331,12 @@ flood_spec ip daddr . tcp dport . meta l4proto . ip saddr
 perf_duration  0
 "
 
+# Definition of tests for bugs reported in the past:
+# display      display text for test report
+TYPE_flush_remove_add="
+display                Add two elements, flush, re-add
+"
+
 # Set template for all tests, types and rules are filled in depending on test
 set_template='
 flush ruleset
@@ -440,6 +450,8 @@ setup_set() {
 
 # Check that at least one of the needed tools is available
 check_tools() {
+       [ -z "${tools}" ] && return 0
+
        __tools=
        for tool in ${tools}; do
                if [ "${tool}" = "nc" ] && [ "${proto}" = "udp6" ] && \
@@ -1025,7 +1037,7 @@ format_noconcat() {
 add() {
        if ! nft add element inet filter test "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1045,7 +1057,7 @@ add_perf() {
 add_perf_norange() {
        if ! nft add element netdev perf norange "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1054,7 +1066,7 @@ add_perf_norange() {
 add_perf_noconcat() {
        if ! nft add element netdev perf noconcat "${1}"; then
                err "Failed to add ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1063,7 +1075,7 @@ add_perf_noconcat() {
 del() {
        if ! nft delete element inet filter test "${1}"; then
                err "Failed to delete ${1} given ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1134,7 +1146,7 @@ send_match() {
                err "  $(for f in ${src}; do
                         eval format_\$f "${2}"; printf ' '; done)"
                err "should have matched ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
        nft reset counter inet filter test >/dev/null
@@ -1160,7 +1172,7 @@ send_nomatch() {
                err "  $(for f in ${src}; do
                         eval format_\$f "${2}"; printf ' '; done)"
                err "should not have matched ruleset:"
-               err "$(nft list ruleset -a)"
+               err "$(nft -a list ruleset)"
                return 1
        fi
 }
@@ -1430,6 +1442,23 @@ test_performance() {
        kill "${perf_pid}"
 }
 
+test_bug_flush_remove_add() {
+       set_cmd='{ set s { type ipv4_addr . inet_service; flags interval; }; }'
+       elem1='{ 10.0.0.1 . 22-25, 10.0.0.1 . 10-20 }'
+       elem2='{ 10.0.0.1 . 10-20, 10.0.0.1 . 22-25 }'
+       for i in `seq 1 100`; do
+               nft add table t ${set_cmd}      || return ${KSELFTEST_SKIP}
+               nft add element t s ${elem1}    2>/dev/null || return 1
+               nft flush set t s               2>/dev/null || return 1
+               nft add element t s ${elem2}    2>/dev/null || return 1
+       done
+       nft flush ruleset
+}
+
+test_reported_issues() {
+       eval test_bug_"${subtest}"
+}
+
 # Run everything in a separate network namespace
 [ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
 tmp="$(mktemp)"
@@ -1438,9 +1467,15 @@ trap cleanup EXIT
 # Entry point for test runs
 passed=0
 for name in ${TESTS}; do
-       printf "TEST: %s\n" "${name}"
-       for type in ${TYPES}; do
-               eval desc=\$TYPE_"${type}"
+       printf "TEST: %s\n" "$(echo ${name} | tr '_' ' ')"
+       if [ "${name}" = "reported_issues" ]; then
+               SUBTESTS="${BUGS}"
+       else
+               SUBTESTS="${TYPES}"
+       fi
+
+       for subtest in ${SUBTESTS}; do
+               eval desc=\$TYPE_"${subtest}"
                IFS='
 '
                for __line in ${desc}; do
index 3a779c0..39559d7 100644 (file)
@@ -2,4 +2,5 @@ pidfd_open_test
 pidfd_poll_test
 pidfd_test
 pidfd_wait
+pidfd_fdinfo_test
 pidfd_getfd_test
index d646953..2af9d39 100644 (file)
@@ -4,7 +4,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
 CLANG_FLAGS += -no-integrated-as
 endif
 
-CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \
+CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \
          $(CLANG_FLAGS)
 LDLIBS += -lpthread
 
@@ -19,6 +19,8 @@ TEST_GEN_PROGS_EXTENDED = librseq.so
 
 TEST_PROGS = run_param_test.sh
 
+TEST_FILES := settings
+
 include ../lib.mk
 
 $(OUTPUT)/librseq.so: rseq.c rseq.h rseq-*.h
index 2d93d65..55198ec 100644 (file)
@@ -6,4 +6,6 @@ TEST_GEN_PROGS = rtctest
 
 TEST_GEN_PROGS_EXTENDED = setdate
 
+TEST_FILES := settings
+
 include ../lib.mk
index 477bc61..c03af46 100644 (file)
@@ -57,3 +57,4 @@ CONFIG_NET_IFE_SKBMARK=m
 CONFIG_NET_IFE_SKBPRIO=m
 CONFIG_NET_IFE_SKBTCINDEX=m
 CONFIG_NET_SCH_FIFO=y
+CONFIG_NET_SCH_ETS=m
index d65a0fa..eda7b62 100644 (file)
@@ -742,9 +742,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                guest_enter_irqoff();
 
                if (has_vhe()) {
-                       kvm_arm_vhe_guest_enter();
                        ret = kvm_vcpu_run_vhe(vcpu);
-                       kvm_arm_vhe_guest_exit();
                } else {
                        ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);
                }
index 204d210..cc94ccc 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <kvm/arm_arch_timer.h>
 #include <linux/tracepoint.h>
+#include <asm/kvm_arm.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm